Related
I have a canvas (with fabricjs working on) where I put rectangles of different colors but with the 50% opacity of the fill color by default.
At the end, I want to set the opacity of every rectangle selected to 100% with the respective color. I'm having difficulties identifying the color of every rectangle, so I can pass from "rgba(255,0,0,0.5)" to "rgba(255,0,0,1)", and from "rgba(0,255,0,0.5)" to "rgba(0,255,0,1)" (for example).
This is the code right now:
function fillColor() {
var objs = canvas.getActiveObjects();
if (!objs) return;
objs.forEach(function (obj) {
if (obj instanceof fabric.Path) {
obj.setStroke('rgba(242,0,222,1)');
} else {
obj.set("fill", 'rgba(242,0,222,1)');
}
canvas.renderAll();
});
}
This only converts every selected object to a 'rgba(242,0,222,1)'.
And I wanted to be like:
function fillColorOb() {
var objs = canvas.getActiveObjects();
if (!objs) return;
objs.forEach(function (obj) {
if (obj instanceof fabric.Path) {
obj.setStroke('rgba(242,0,222,1)');
} else {
//if (obj.color == 'rgba(242,0,222,0.5)') {
//obj.set("fill", 'rgba(242,0,222,1)');
//}
//if (obj.color == 'rgba(242,0,0,0.5)') {
//obj.set("fill", 'rgba(242,0,0,1)');
//}
}
canvas.renderAll();
});
}
So that way, with the if I can identify first the rectangle color and then set the rgba as I want.
Thanks:)
I didn't come up with the exact idea, but here is a solution:
I have struggle trying to extract information from an object selected, but there is a thing you can do. You can export all the canvas into a JSON file:
JSON.stringify(canvas);
And then interpret that JSON file
{
"version": "5.2.4",
"objects": [{
"type": "rect",
"version": "5.2.4",
"originX": "left",
"originY": "top",
"left": 318,
"top": 13,
"width": 100,
"height": 100,
"fill": "rgba(242,0,222,0.5)",
"stroke": "rgba(242,0,222,1)",
"strokeWidth": 2,
"strokeDashArray": null,
"strokeLineCap": "butt",
"strokeDashOffset": 0,
"strokeLineJoin": "miter",
"strokeUniform": false,
"strokeMiterLimit": 4,
"scaleX": 1,
"scaleY": 1,
"angle": 0,
"flipX": false,
"flipY": false,
"opacity": 1,
"shadow": null,
"visible": true,
"backgroundColor": "",
"fillRule": "nonzero",
"paintFirst": "fill",
"globalCompositeOperation": "source-over",
"skewX": 0,
"skewY": 0,
"rx": 10,
"ry": 10,
"name": "ly1"
}, {
"type": "circle",
"version": "5.2.4",
"originX": "left",
"originY": "top",
"left": 114,
"top": 119,
"width": 253.49,
"height": 253.49,
"fill": "rgba(0,255,132,0.5)",
"stroke": "rgba(0,255,132,1)",
"strokeWidth": 2,
"strokeDashArray": null,
"strokeLineCap": "butt",
"strokeDashOffset": 0,
"strokeLineJoin": "miter",
"strokeUniform": false,
"strokeMiterLimit": 4,
"scaleX": 1,
"scaleY": 1,
"angle": 0,
"flipX": false,
"flipY": false,
"opacity": 1,
"shadow": null,
"visible": true,
"backgroundColor": "",
"fillRule": "nonzero",
"paintFirst": "fill",
"globalCompositeOperation": "source-over",
"skewX": 0,
"skewY": 0,
"radius": 126.74605507255723,
"startAngle": 0,
"endAngle": 360,
"name": "ly4"
}]
}
And then all the information you'll need you can find it on that file.
That's not what I was exactly expecting but it works, and I had to export it anyways so :)
Hope it helped anyone!
I have created the following image as fabricjs-json:
The json looks like the following:
{
"version": "5.2.1",
"objects": [
{
"type": "circle",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": "100",
"top": "100",
"width": "60",
"height": "60",
"fill": "#e53e3e",
"name": "a",
"radius": "30",
"stroke": null,
"padding": "0"
},
{
"type": "triangle",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": "80",
"top": "229.13",
"fill": "#e0da2e",
"name": "b",
"height": "100",
"width": "100",
"stroke": null,
"padding": "0"
},
{
"type": "rect",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": "303.02",
"top": "69.96",
"width": "50",
"height": "50",
"fill": "#4976d0",
"name": "c",
"rx": "0",
"ry": "0",
"stroke": null,
"padding": "0"
},
{
"type": "image",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": "272.23",
"top": "287.63",
"width": "400",
"height": "400",
"scaleX": "0.58",
"scaleY": "0.58",
"name": "d",
"rx": "0",
"ry": "0",
"stroke": null,
"padding": "0",
"src": "https:\/\/picsum.photos\/id\/1014\/400",
"crossOrigin": null
},
{
"type": "textbox",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": "210.97",
"top": "100",
"width": "265.14180221557615",
"height": "25.99",
"fill": "#000000",
"angle": "33.4",
"name": "e",
"text": "This awesome image",
"textAlign": "left",
"fontSize": "23",
"charSpacing": "7",
"lineHeight": "1.16",
"fontWeight": "400",
"fontFamily": "Inter",
"fontStyle": "normal",
"textBackgroundColor": null,
"maxHeight": "487",
"stroke": null,
"padding": "20"
}
],
"background": "#24bd0f"
}
I created the following script to convert the json to an image:
var fs = require('fs'),
fabric = require('fabric').fabric,
out = fs.createWriteStream(__dirname + '/output.png');
let jsonstr = fs.readFileSync(__dirname + '/json/test_json.json', 'utf-8');
let json = JSON.parse(jsonstr);
var canvas = new fabric.StaticCanvas(null, { width: 500, height: 500 });
canvas.loadFromJSON(json, function() {
canvas.renderAll.bind(canvas);
var dataUrlOutput = canvas.toDataURL(); // png is default format
console.log(dataUrlOutput)
fs.writeFile(__dirname + '/output/output.png', dataUrlOutput, function(err) {
if (err) throw err;
});
});
This is my package.json:
{
"name": "jsonToImage",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"canvas": "^2.9.3",
"fabric": "^5.2.4"
}
}
However, when opening the image I get:
I created the following sandbox to parse the json:
Codesandbox Example - JSONtoIMAGE
Any suggestions what I am doing wrong?
UPDATE
I checked the dataUrlOutput from the script and I get the following:
As you can see half of the elements are there.
There seem to be a few things going on, namely the formatting of your JSON, rendering the canvas, and saving the file in Node.
Formatting your JSON
The numbers in your json file are enclosed in quotes (e.g. "left": "100"), while for those numerical values, fabric.js expects them not to be in quotes (e.g. "left": 100). When there are quotes around the numbers, fabric.js seems to quasi-load some objects, but not others.
When you're saving your canvas as JSON, you can use JSON.stringify to ensure that the formatting is preserved. For example, JSON.stringify(canvas.toJSON());
Rendering the canvas
You're calling canvas.renderAll.bind(canvas), which creates a new function but doesn't call it. It should just be canvas.renderAll().
Saving an image
Saving a data url directly as a text file does not create an image in an encoded binary file. While you could use the data url to create a binary file (like from this answer), fabric.js adds some convenience functions to save a file, namely canvas.createPNGStream().
It looks something like this (thanks to this answer):
var out = fs.createWriteStream(__dirname + '/output.png');
var stream = canvas.createPNGStream();
stream.pipe(out);
All together
With the modified JSON and code, the results look something like this:
Your data file, 'json/test_json.json'
{
"version": "5.2.1",
"objects": [
{
"type": "circle",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": 100,
"top": 100,
"width": 60,
"height": 60,
"fill": "#e53e3e",
"name": "a",
"radius": 30,
"stroke": null,
"padding": 0
},
{
"type": "triangle",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": 80,
"top": 229.13,
"fill": "#e0da2e",
"name": "b",
"height": 100,
"width": 100,
"stroke": null,
"padding": 0
},
{
"type": "rect",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": 303.02,
"top": 69.96,
"width": 50,
"height": 50,
"fill": "#4976d0",
"name": "c",
"rx": 0,
"ry": 0,
"stroke": null,
"padding": 0
},
{
"type": "image",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": 272.23,
"top": 287.63,
"width": 400,
"height": 400,
"scaleX": 0.58,
"scaleY": 0.58,
"name": "d",
"rx": 0,
"ry": 0,
"stroke": null,
"padding": 0,
"src": "https:\/\/picsum.photos\/id\/1014\/400",
"crossOrigin": null
},
{
"type": "textbox",
"version": "5.2.1",
"originX": "center",
"originY": "center",
"left": 210.97,
"top": 100,
"width": 265.14180221557615,
"height": 25.99,
"fill": "#000000",
"angle": 33.4,
"name": "e",
"text": "This awesome image",
"textAlign": "left",
"fontSize": 23,
"charSpacing": 7,
"lineHeight": 1.16,
"fontWeight": 400,
"fontFamily": "Inter",
"fontStyle": "normal",
"textBackgroundColor": null,
"maxHeight": 487,
"stroke": null,
"padding": 20
}
],
"background": "#24bd0f"
}
And your node.js program:
var fs = require('fs'),
fabric = require('fabric').fabric,
out = fs.createWriteStream(__dirname + '/output.png');
let jsonstr = fs.readFileSync(__dirname + '/json/test_json.json', 'utf-8');
let json = JSON.parse(jsonstr);
var canvas = new fabric.StaticCanvas(null, { width: 500, height: 500 });
canvas.loadFromJSON(json, function() {
canvas.renderAll();
var stream = canvas.createPNGStream();
stream.pipe(out);
out.on('finish', function () {
// do something here
});
});
More reading:
http://fabricjs.com/fabric-intro-part-4 (the 'Fabric on Node.js' section)
We have upgraded chart.js from version 2 to 3 and now the following is not working. To make a single value, which should be displayed as a line, more readable, the value was simply displayed three times and only a section of the x axis was displayed. As a result, a straight line runs completely from left to right through the whole chart.
Here is an image of what it looked like in V2 vs. now in V3:
Img-Description: left chart with version 2, all lines and areas go from left to right; right chart with version 3, the line starts left but end in the middle and the areas go down after the middle datapoint
We are using the min/max attributes for the x scale. Any ideas?
This is my ChartConfiguration:
const ctx = document.getElementById("ctx").getContext("2d");
const configuration = {
"type": "line",
"data": {
"labels": ["", "2015", ""],
"datasets": [{
"data": [8, 8, 8],
"type": "line",
"label": "Umsatzrentabilität",
"borderColor": "#FF8F00",
"backgroundColor": "#FF8F00",
"fill": false,
"yAxisID": "yRight",
}, {
"data": [18330.47727032784, 18330.47727032784, 18330.47727032784],
"type": "bar",
"label": "Gesamtleistung in TEUR",
"backgroundColor": "rgba(0,152,100,0.8)",
"hoverBackgroundColor": "#009864",
"barPercentage": 0.5,
}, {
"data": [12, 12, 12],
"type": "line",
"label": "Branchenmitte von",
"fill": "+1",
"borderColor": "#dddddd",
"backgroundColor": "rgba(60, 60, 60, 0.06)",
"yAxisID": "yRight",
}, {
"data": [9, 9, 9],
"type": "line",
"label": "Branchenmitte bis",
"fill": "-1",
"borderColor": "#dddddd",
"backgroundColor": "rgba(60, 60, 60, 0.06)",
"yAxisID": "yRight",
}],
}, "options": {
"maintainAspectRatio": false,
"responsive": true,
"scales": {
"x": {
"axis": "x",
"grid": {
"borderColor": "#bbbbbb",
"color": "#f0f0f0",
"display": true,
"drawTicks": true,
"drawBorder": true,
"drawOnChartArea": true,
},
"min": "2015",
"max": "2015",
"type": "category",
"bounds": "data",
"id": "x",
"position": "bottom",
},
"y": {
"axis": "y",
"title": {
"align": "center",
"display": true,
"text": "Gesamtleistung in TEUR",
"color": "#666",
},
"suggestedMax": 21996.572724393405,
"suggestedMin": 0,
"grid": {
"borderColor": "#bbbbbb",
"display": true,
"drawBorder": true,
"drawTicks": true,
"drawOnChartArea": true,
},
"type": "linear",
"id": "y",
"position": "left",
},
"yRight": {
"axis": "y",
"type": "linear",
"display": true,
"position": "right",
"title": {
"align": "center",
"display": true,
"text": "Umsatzrentabilität (%)",
"color": "#666",
},
"suggestedMax": 14.4,
"suggestedMin": 0,
"grid": {
"borderColor": "#bbbbbb",
"color": "#f0f0f0",
"display": true,
"drawBorder": true,
"drawOnChartArea": false,
},
"id": "yRight",
},
},
},
};
new Chart(ctx, configuration);
#ctx {
min-height: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<canvas id="ctx" />
Here is a fiddle with the current version: https://jsfiddle.net/Sue10bach/7q3n6wvb/
I am creating a pie chart using AmCharts. I am trying to alter the legend lablelText to show the title, percent and value. I have tried the following which is not working: (This is being passed to the AmCharts.makeChart() method
"legend": {
"align": "center",
"position": "right",
"marginRight": 21,
"markerType": "circle",
"right": -4,
"labelText": "[[title]]: [[percents]]% $[[value]]",
},
In the end I discovered I should be using valueText not labelText and so was able to change to this:
"legend": {
"align": "center",
"position": "bottom",
"marginRight": 21,
"markerType": "circle",
"right": -4,
"labelText": "[[title]]",
"valueText": " $[[value]] [[percents]]%",
"valueWidth": 80,
"textClickEnabled": true
},
I'm trying to find a free charting library for JS that does not require jQuery and is able to add vertical cursor bars at indicated locations. Interactivity would be nice. I only need a line chart, no doughnuts required. Anyone know if this creature exists?
var chartJSON = {
"type": "line",
"background-color": "#fff",
"border-color": "#dae5ec",
"border-width": "1px",
"title": {
"margin-top": "7px",
"margin-left": "12px",
"text": "TODAY'S SALES",
"background-color": "none",
"shadow": 0,
"text-align": "left",
"font-family": "Arial",
"font-size": "11px",
"font-color": "#707d94"
},
"plot": {
"animation": {
"effect": "ANIMATION_SLIDE_LEFT"
}
},
"plotarea": {
"margin": "50px 25px 70px 46px"
},
"scale-y": {
"values": "0:100:25",
"line-color": "none",
"guide": {
"line-style": "solid",
"line-color": "#d2dae2",
"line-width": "1px",
"alpha": 0.5
},
"tick": {
"visible": false
},
"item": {
"font-color": "#8391a5",
"font-family": "Arial",
"font-size": "10px",
"padding-right": "5px"
}
},
"scale-x": {
"line-color": "#d2dae2",
"line-width": "2px",
"values": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
"tick": {
"line-color": "#d2dae2",
"line-width": "1px"
},
"guide": {
"visible": "false"
},
"markers": [{
"type": "area",
"range": [5, 7],
"background-color": "red",
"alpha": 0.3,
"label": {
"text": "Summer Sale",
"alpha": 0.5
}
}],
"item": {
"font-color": "#8391a5",
"font-family": "Arial",
"font-size": "10px",
"padding-top": "5px"
}
},
"legend": {
"layout": "2x2",
"background-color": "none",
"shadow": 0,
"margin": "auto auto 15 auto",
"border-width": 0,
"item": {
"font-color": "#707d94",
"font-family": "Arial",
"padding": "0px",
"margin": "0px",
"font-size": "9px"
},
"marker": {
"show-line": "true",
"type": "match",
"font-family": "Arial",
"font-size": "10px",
"size": 4,
"line-width": 2,
"padding": "3px"
}
},
"crosshair-x": {
"lineWidth": 1,
"line-color": "#707d94",
"plotLabel": {
"shadow": false,
"font-color": "#ffffff",
"font-family": "Arial",
"font-size": "10px",
"padding": "5px 10px",
"border-radius": "5px",
"alpha": 1
},
"scale-label": {
"font-color": "#ffffff",
"background-color": "#707d94",
"font-family": "Arial",
"font-size": "10px",
"padding": "5px 10px",
"border-radius": "5px"
}
},
"tooltip": {
"visible": false
},
"series": [{
"values": [69, 68, 54, 48, 70, 74, 98, 70, 72, 68, 49, 69],
"text": "Kenmore",
"line-color": "#4dbac0",
"line-width": "2px",
"shadow": 0,
"marker": {
"background-color": "#fff",
"size": 3,
"border-width": 1,
"border-color": "#36a2a8",
"shadow": 0
},
"palette": 0
}, {
"values": [51, 53, 47, 60, 48, 52, 75, 52, 55, 47, 60, 48],
"text": "Craftsman",
"line-width": "2px",
"line-color": "#25a6f7",
"shadow": 0,
"marker": {
"background-color": "#fff",
"size": 3,
"border-width": 1,
"border-color": "#1993e0",
"shadow": 0
},
"palette": 1,
"visible": 1
}, {
"values": [42, 43, 30, 50, 31, 48, 55, 46, 48, 32, 50, 38],
"text": "DieHard",
"line-color": "#ad6bae",
"line-width": "2px",
"shadow": 0,
"marker": {
"background-color": "#fff",
"size": 3,
"border-width": 1,
"border-color": "#975098",
"shadow": 0
},
"palette": 2,
"visible": 1
}, {
"values": [25, 15, 26, 21, 24, 26, 33, 25, 15, 25, 22, 24],
"text": "Land's End",
"line-color": "#f3950d",
"line-width": "2px",
"shadow": 0,
"marker": {
"background-color": "#fff",
"size": 3,
"border-width": 1,
"border-color": "#d37e04",
"shadow": 0
},
"palette": 3
}]
}
zingchart.render({
id: "myChart",
height: 300,
width: 500,
data: chartJSON
});
<script src="http://www.zingchart.com/playground/lib/zingchart/zingchart-html5-min.js"></script>
<div id="myChart"></div>
Are you referring to something like this? This was done with ZingChart, which is free to use. A marker was set on the x-axis with a range and lowered opacity.
Let me know if you were looking for something else and I'll put together another demo. I'm on the team at ZingChart and happy to help :)
You can do this with amCharts, here is a stacked area chart demo. If you don't need a fill, simply set fillAlphas to 0. and stackType of value axis to "none"
Disclaimer: I am the author of amCharts.
Here is an example made with D3js Framework, it might interest you..