FabricJS convert json to png - javascript

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)

Related

limit x axis while keeping lines into offscreen

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/

How to change the color of series(grouped column chart) only with json object(without js function) on Highchart?

I actually work with a tool named Jedox that allow me to use the Highchart.js library to make chart. So I try to make a simple chart with 2 series and 4 columns it's a grouped column chart(clustered bar chart). I saw on Highchart that is possible to change the color of a series with the array "colors" but when I use it it didn't work. Why ? I also try to use colorByPoint, it's working but it's not what I want because It color catogeries but in the categories there is different series and I want that each series have a precise color. How can I do that ?
Before you see the code here's some precision: I put "undefined" on color attribute because there is no way to delete those attribute so I put them into a default value. Normally when the value is set to "undefined" the color correspond to one of the color in the "colors" array.
One important thing you have to know before help me : I can't use JS, I can only use JSON that's all.
Here's my code:(it's just a json)
"chart": {
"type": "column",
"zoomType": "xy",
"borderRadius": 0,
"events": {},
"height": 300,
"width": 400,
"backgroundColor": "#FFFFFF",
"borderWidth": 1,
"borderColor": "#D8D8D8",
"plotBackgroundColor": null,
"plotBorderWidth": 0,
"plotBorderColor": "#000100",
"spacingTop": 20
},
"plotOptions": {
"series": {
"minPointLength": 1,
"dataLabels": {
"enabled": false,
"inside": false,
"rotation": 0,
"x": 0,
"y": 0,
"style": {
"fontFamily": "Arial",
"fontSize": 9,
"color": "#366092",
"fontWeight": "normal",
"fontStyle": "regular"
}
},
"cursor": null,
"point": {
"events": {}
}
}
},
"legend": {
"symbolRadius": 0,
"backgroundColor": null,
"borderWidth": 0,
"borderColor": "#000100",
"itemStyle": {
"fontFamily": "Arial",
"fontWeight": "normal",
"fontSize": "11px",
"color": "#445862",
"fontStyle": ""
},
"floating": false,
"align": "center",
"verticalAlign": "bottom",
"layout": "horizontal",
"reversed": false
},
"title": {
"text": null
},
"series": [
{
"name": "Expected",
"data": [
1,
5
],
"color": "undefined",
"id": 0,
"property": "dcColumnClustered",
"type": "column",
"yAxis": 0,
"zIndex": 2,
"borderWidth": 0,
"dataLabels": {
"enabled": false
}
},
{
"name": "Current",
"data": [
2,
3
],
"color": "undefined",
"id": 1,
"property": "dcColumnClustered",
"type": "column",
"yAxis": 0,
"zIndex": 2,
"borderWidth": 0,
"dataLabels": {
"enabled": false
}
}
],
"xAxis": [
{
"id": "x_0",
"axtype": "xAxis",
"labels": {
"enabled": true,
"style": {
"fontFamily": "Arial",
"fontWeight": "normal",
"fontSize": "11px",
"color": "#445862",
"fontStyle": ""
},
"autoRotation": false
},
"categories": [
"col1",
"col2"
],
"title": {
"style": {
"fontFamily": "Arial",
"fontWeight": "normal",
"fontSize": "11px",
"color": "#445862",
"fontStyle": ""
},
"text": ""
},
"tickInterval": null,
"minorTickInterval": null,
"gridLineWidth": 0,
"minorGridLineWidth": 0,
"reversed": false,
"reversedStacks": false
}
],
"yAxis": [
{
"id": "y_0",
"axtype": "yAxis",
"opposite": false,
"labels": {
"enabled": true,
"style": {
"fontFamily": "Arial",
"fontWeight": "normal",
"fontSize": "11px",
"color": "#445862",
"fontStyle": ""
},
"autoRotation": false
},
"gridLineWidth": 1,
"gridLineColor": "#D8D8D8",
"title": {
"text": "",
"style": {
"fontFamily": "Arial",
"fontWeight": "normal",
"fontSize": "11px",
"color": "#445862",
"fontStyle": ""
}
},
"tickInterval": null,
"minorTickInterval": null,
"reversed": false,
"reversedStacks": true
}
],
"tooltip": {
"enabled": true
},
"colors": [
"#FF0000",
"#0000FF"
]
Here's my Fiddle
Here's the goal I want to reach
The default color value is undefined, not a string "undefined". (If undefined value isn't allowed by Jedox, put null instead)
"series": [{
"color": undefined,
...
},
{
"color": undefined,
...
}
]
Live demo: https://jsfiddle.net/BlackLabel/zocj5a0b/
API Reference: https://api.highcharts.com/highcharts/series.column.color

remove specific element from json

i have json like
{
"type": "textbox",
"originX": "center",
"originY": "top",
"left": 1289.6,
"top": 695.43,
"width": 244.84,
"height": 36.72,
"fill": "rgb(0, 0, 0)",
"stroke": null,
"strokeWidth": 1,
"strokeDashArray": null,
"strokeLineCap": "butt",
"strokeLineJoin": "miter",
"strokeMiterLimit": 10,
"scaleX": 1,
"scaleY": 1,
"angle": 0,
"flipX": false,
"flipY": false,
"opacity": 1,
"shadow": null,
"visible": true,
"clipTo": null,
"backgroundColor": "",
"fillRule": "nonzero",
"globalCompositeOperation": "source-over",
"transformMatrix": null,
"lockMovementX": false,
"lockMovementY": false,
"evented": true,
"text": "FROM ONLY £199",
"fontSize": 25,
"fontWeight": "",
"fontFamily": "'trebuchet ms'",
"fontStyle": "",
"lineHeight": 1.3,
"textDecoration": "",
"textAlign": "left",
"textBackgroundColor": "",
"styles": {
"0": {
"1": {
"fontFamily": "'trebuchet ms'",
"fontSize": 25,
"fontWeight": "",
"fontStyle": ""
},
"2": {
"fontFamily": "'trebuchet ms'",
"fontSize": 25,
"fontWeight": "",
"fontStyle": ""
}
}
},
"minWidth": 20
}
You can see there is styles attribute at second last, it has many other objects. when you open ony one from that you will see fontFamily, fontSize fontWeight. I want to remove fontWeight from it. For this i tried this code
if (typeof indexs['styles'] != "undefined") {
for (rowIndex in indexs['styles']) {
for (letterIndex in indexs['styles'][rowIndex]) {
if (indexs['styles'][rowIndex][letterIndex].fontWeight && indexs['styles'][rowIndex][letterIndex].fontWeight=='') {
delete indexs['styles'][rowIndex][letterIndex]['fontWeight'];
}
}
}
}
But not deleting that attribute. Am i doing anything wrong there?
You have to update this:
if (indexs['styles'][rowIndex][letterIndex].fontWeight=='') {
delete indexs['styles'][rowIndex][letterIndex]['fontWeight'];
}
because a blank value "" is a falsy value and
indexs['styles'][rowIndex][letterIndex].fontWeight
results as false and && should work when both are true.
try this too...to check whether the key "fontWeight" is there before checking for null value...
if (typeof indexs['styles'] != "undefined") {
for (rowIndex in indexs['styles']) {
for (letterIndex in indexs['styles'][rowIndex]) {
if (indexs['styles'][rowIndex][letterIndex].hasOwnProperty("fontWeight") && indexs['styles'][rowIndex][letterIndex].fontWeight=='') {
delete indexs['styles'][rowIndex][letterIndex]['fontWeight'];
}
}
}
}
});

Read multiple barcode from a single image using php or javascript

Is there any way to scan multiple bar-codes from a single image at a time using PHP or JavaScript. I have googled, but can scan only single barcode from an image.
I have tried this code : https://gist.github.com/tobytailor/421369
You could also use a Barcode Recognition API like the one from HP IDOL OnDemand (I work for HP). I ran the image above through the online console for a quick test and was able to extract the following information from the image file...
{
"barcode": [
{
"text": "CODE128",
"barcode_type": "code-128",
"left": 1498,
"top": 552,
"width": 598,
"height": 262,
"additional_information": {}
},
{
"text": "CODE39",
"barcode_type": "code-39",
"left": 300,
"top": 552,
"width": 768,
"height": 262,
"additional_information": {}
},
{
"text": "0012345678905",
"barcode_type": "ean-13",
"left": 1480,
"top": 1466,
"width": 619,
"height": 260,
"additional_information": {
"country": "U.S. and Canada"
}
},
{
"text": "1234567890128",
"barcode_type": "ean-13",
"left": 366,
"top": 1922,
"width": 584,
"height": 260,
"additional_information": {
"country": "U.S. (reserved for later use)"
}
},
{
"text": "01234565",
"barcode_type": "ean-8",
"left": 1696,
"top": 2022,
"width": 390,
"height": 160,
"additional_information": {}
},
{
"text": "012345",
"barcode_type": "codabar",
"left": 300,
"top": 1010,
"width": 672,
"height": 260,
"additional_information": {}
},
{
"text": "CODE93",
"barcode_type": "code-93",
"left": 300,
"top": 1466,
"width": 730,
"height": 260,
"additional_information": {}
},
{
"text": "00123456",
"barcode_type": "i25",
"left": 1501,
"top": 1010,
"width": 264,
"height": 260,
"additional_information": {}
},
{
"text": "00",
"barcode_type": "i25",
"left": 1394,
"top": 1029,
"width": 242,
"height": 242,
"additional_information": {}
}
]
}

How to alter legend labelText for AmCharts?

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
},

Categories

Resources