{
"objects": [{
"type": "i-text",
"originX": "left",
"originY": "top",
"left": 253.75,
"top": 377.4,
"width": 293.49609375,
"height": 45.199999999999996,
"fill": "#454545",
"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,
"skewX": 0,
"skewY": 0,
"text": "Start typing here",
"fontSize": 40,
"fontWeight": "normal",
"fontFamily": "arial",
"fontStyle": "",
"lineHeight": 1.16,
"textDecoration": "",
"textAlign": "left",
"textBackgroundColor": "",
"charSpacing": 0,
"originalScaleX": 1,
"originalScaleY": 1,
"originalLeft": 253.751953125,
"originalTop": 377.4,
"lockMovementX": false,
"lockMovementY": false,
"lockScalingX": false,
"lockScalingY": false,
"lockUniScaling": false,
"lockRotation": false,
"id": 8454,
"styles": {}
}],
"background": "#ffffff",
"height": 800,
"width": 801,
"originalHeight": 800,
"originalWidth": 801
}
{
"objects": [{
"type": "i-text",
"originX": "left",
"originY": "top",
"left": 253.75,
"top": 377.4,
"width": 293.49609375,
"height": 45.199999999999996,
"fill": "#454545",
"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,
"skewX": 0,
"skewY": 0,
"text": "Start typing here",
"fontSize": 40,
"fontWeight": "normal",
"fontFamily": "arial",
"fontStyle": "",
"lineHeight": 1.16,
"textDecoration": "",
"textAlign": "left",
"textBackgroundColor": "",
"charSpacing": 0,
"originalScaleX": 1,
"originalScaleY": 1,
"originalLeft": 253.751953125,
"originalTop": 377.4,
"lockMovementX": false,
"lockMovementY": false,
"lockScalingX": false,
"lockScalingY": false,
"lockUniScaling": false,
"lockRotation": false,
"id": 6668,
"styles": {}
}],
"background": "#ffffff",
"height": 800,
"width": 801,
"originalHeight": 800,
"originalWidth": 801
}
i have this 2 fabric.js json object which i want to concat and load to canvas by using fabric loadJSON method??
There are many options depending on what Sagar Adke is ultimately trying to achieve. However, I think these might be closer to what he's looking for:
OPTION 1:
Load the canvas with json1 stringify'ing first, clone the object since loading again will clear the canvas, load the canvas with json2 stringify'ing first, and then add the cloned object.
canvas.loadFromJSON(JSON.stringify(json1), canvas.renderAll.bind(canvas));
var item = canvas.item(0).clone();
canvas.loadFromJSON(JSON.stringify(json2), canvas.renderAll.bind(canvas));
// only needed since objects are identical and I wanted to show both objects
item.set({
top: item.top - 70
});
canvas.add(item);
canvas.renderAll();
Working JSFiddle, http://jsfiddle.net/rekrah/wxjnu7pd/.
OPTION 2:
Push json2 object onto json1 object stack, and then load the canvas with json1 stringify'ing first.
json1.objects.push(json2.objects[0]);
// the next line will put both objects on top of each other, since they're identical
canvas.loadFromJSON(JSON.stringify(json1), canvas.renderAll.bind(canvas));
canvas.renderAll();
Working JSFiddle, http://jsfiddle.net/rekrah/okb2uj1m/.
OPTION 3:
No need to stringify json first with this option, just pass an array of fabric objects to enlivenObjects (in fabric.util), and then add each object to the canvas in its callback.
fabric.util.enlivenObjects([json1.objects[0], json2.objects[0]], function(objects) {
var origRenderOnAddRemove = canvas.renderOnAddRemove;
canvas.renderOnAddRemove = false;
objects.forEach(function(o, i) {
// IF only needed since objects are identical and I wanted to show both objects
if (i == 0) o.set({
top: o.top - 70
});
canvas.add(o);
});
canvas.renderOnAddRemove = origRenderOnAddRemove;
canvas.renderAll();
});
Working JSFiddle, http://jsfiddle.net/rekrah/jnkLjrn4/.
(Option 3 credit goes to a FabricJS master, https://stackoverflow.com/a/19364574/3389046)
For this kind of object manipulation, I always have underscore.js ready. It's the first js library I import when starting a new project.
http://underscorejs.org
Take a look at: _.extend (better even, take a look at the whole lib ;))
_.extend({name: 'moe'}, {age: 50});
=> {name: 'moe', age: 50}
Related
I am using Amchart's Gantt chart.
The segments are divided by dates.
I need the chart's navigator initial location will be between two dates, and not to be applied all over the chart.
the current behavior:
The expected result:
I tried adding 'startDate' and 'endDate' but without success.
my Amchat;s configurations:
<AmCharts.React
className="my-class"
style={{
width: '50%',
height: '250px'
}}
options={
{
"height": "500",
"hideCredits":true,
"type": "gantt",
"theme": "light",
"marginRight": 70,
"period": "DD",
"dataDateFormat": "YYYY-MM-DD",
"columnWidth": 0.45,
"valueAxis": {
"type": "date"
},
"graph": {
"lineAlpha": 1,
"lineColor": "#fff",
"fillAlphas": 0.85,
"showAllValueLabels": false,
"cornerRadiusTop": 4
},
"rotate": true,
"categoryField": "category",
"segmentsField": "segments",
"colorField": "color",
"startDateField": "start",
"endDateField": "end",
"dataProvider": this.state.dataProvider,
"valueScrollbar": {
"selectedBackgroundColor": '#f3faff',
"selectedBackgroundAlpha": 1,
"autoGridCount": false
},
"chartCursor": {
"cursorColor": "#55bb76",
"valueBalloonsEnabled": false,
"cursorAlpha": 0,
"valueLineAlpha": 0.5,
"valueLineBalloonEnabled": false,
"valueLineEnabled": false,
"zoomable": false,
"valueZoomable": true
},
"export": {
"enabled": false
}
}
}
/>
Thanks.
You can use "zoomToDates(start, end)" property of AmGanttChart. Here is the relevant reference:
AmGanttChart | JavaScript Charts v. 3 | amCharts
Also you can find the usage of the property from that question:
AM Charts initial view using zoomToDates
so im using both ammap and amcharts in one page. the problem is, the amcharts.js always disabling my ammap's legend and make it invisible.
how do i solve this?
amcharts legend settings :
"legend": {
"width" : "100%",
"maxRows": 1,
"position": "bottom",
// "useGraphSettings": true,
"markerSize": 10,
"align" : "center",
},
ammap legend settings :
"legend" : {
"width": "30%",
"useGraphSettings": true,
"marginRight": 27,
"marginLeft": 27,
"equalWidths": false,
"backgroundAlpha": 0.2,
"backgroundColor": "#000000",
"borderColor": "#ffffff",
"top": 450,
"left": 0,
"horizontalGap": 10,
"data": [ {
"title": "Negeri",
"color": "#BF55EC",
// "customMarker": "https://www.amcharts.com/lib/3/images/car.png"
}, {
"title": "Swasta",
"color": "#32C5D2",
"border" : "#000000"
} ],
}
but i dont think the problem lies in my codes. whenever i commented out amcharts.js it's working again.
I'm using ammaps to create a map and trying to create a legend. I'm running in to a weird problem where the legend doesn't appear on initial load but only appears on window resize. Regardless of the window size, on any resize, the legend becomes visible (VERY WEIRD RIGHT?).
Code:
var icon = "M9.875,0.625C4.697,0.625,0.5,4.822,0.5,10s4.197,9.375,9.375,9.375S19.25,15.178,19.25,10S15.053,0.625,9.875,0.625";
var map = AmCharts.makeChart( "mapdiv", {
/**
* this tells amCharts it's a map
*/
"type": "map",
/**
* create data provider object
*/
"dataProvider": {
"mapURL": "https://raw.githubusercontent.com/ggwc82/amcharts/master/unitedKingdomLow.svg",
"getAreasFromMap": false,
"images": [ {
"latitude": 51.5074,
"longitude": 0.1278,
"svgPath": icon,
"scale": 0.7,
"label": "Dagenham Factory",
"labelBackgroundColor": "#ffffff",
"labelColor": "#696D6E",
"labelFontSize": 14,
"labelShiftY": 00,
"color": "#D30000",
"title": "1 Warning",
"url": "http://www.google.co.uk",
"description": "DRM with id 09 is offline"
},
{
"latitude": 53.4808,
"longitude": -2.2426,
"svgPath": icon,
"scale": 0.7,
"label": "Manchester Factory",
"labelBackgroundColor": "#ffffff",
"labelColor": "#696D6E",
"labelFontSize": 14,
"labelShiftY": 0,
"color": "#40D300",
"title": "No Issues",
"url": "http://www.google.co.uk",
"description": ""
},
{
"latitude": 54.9783,
"longitude": -1.6178,
"svgPath": icon,
"scale": 0.7,
"label": "Newcastle Factory",
"labelBackgroundColor": "#ffffff",
"labelColor": "#696D6E",
"labelFontSize": 14,
"labelShiftY": 0,
"color": "#D3D000",
"title": "2 Alerts",
"url": "http://www.google.co.uk",
"description": "DRM with id 23 is inactive. DRM with id 25 is inactive."
}
],
},
/**
* create areas settings
* autoZoom set to true means that the map will zoom-in when clicked on the area
* selectedColor indicates color of the clicked area.
*/
"areasSettings": {
"autoZoom": true,
"unlistedAreasColor": "#C8E1D6",
"selectedColor": "#CC0000"
},
"zoomControl": {
"zoomControlEnabled": false,
"homeButtonEnabled": true,
},
"dragMap": false,
"showDescriptionOnHover": true,
"allLabels": [
{
"text": "Default Factory View - UK Sites",
"bold": true,
"size": 20,
"color": "#696D6E",
"align": "center",
"y": 100
}
],
} );
var legend = new AmCharts.AmLegend();
console.log("hello");
map.addLegend(legend,"legenddiv");
legend.data = [{title:"first", color:"#CC0000", markerType: "circle"},
{title:"second", color:"#00CC00", markerType: "circle"},
{title:"second", color:"#ffff00", markerType: "circle"}]
You're using the makeChart function. This function is an helper which allow you to create in a single call a chart / map, configure it using JSON, display it in the container div passed as first argument and get back the instance previously created.
You're adding the legend to your instance but it's already rendered by the makeChart helper when you're hitting your code adding the legend. So, when adding the legend to an already rendered chart, it'll only be visible when re-rendered which happens when you resize your window.
As specified in the documentation, the AmMap class can not be instantiated explicitly so the use of the makeChart method is mandatory but you can also configure your legend in the JSON config instead of doing it later.
/**
* Legend
*/
"legend": {
"width": 400,
"backgroundAlpha": 1,
"backgroundColor": "#fff",
"borderColor": "#000",
"borderAlpha": 1,
"bottom": 15,
"right": 15,
"horizontalGap": 10,
"data": [{
"title": "first",
"color": "#CC0000",
"markerType": "circle"
}, {
"title": "second",
"color": "#00CC00",
"markerType": "circle"
}, {
"title": "third",
"color": "#ffff00",
"markerType": "circle"
}]
},
I've put a little fiddle based on your question including a legend configured in JSON. The legend is displayed at the same time of the map, no resize or anything required to show it.
The following is the function used to generate a pie chart. Everything is working fine, except for the addLabel parameter.
graphSentiChart:function(graphData) {
if(graphData.length < 1){
$('.dataContentStatsPie').html('No data available')
}
// $(".dataContentAllPie").empty();
var piechart = AmCharts.makeChart("chartPie", {
"type": "pie",
"theme": "light",
"autoMargins": true,
"marginTop": 0,
"marginBottom": 10,
"marginLeft": 0,
"marginRight": 0,
"dataProvider": graphData,
"titleField":"key",
"valueField": "value",
"addLabel": (0, 25, 'Total Tweets= 360'),
"startDuration":0,
"responsive": {
"enabled":true
},
"legend":{
"autoMargins":false,
"marginLeft":20,
"enabled": true,
"spacing":20,
"markerType":"circle",
"horizontalGap" :20,
},
"labelsEnabled":false,
//"balloonText": "[[title]]<br><span style='font-size:14px'><b>[[value]]</b> ([[percents]]%)</span>",
"colorField": "color",
"innerRadius": "60%",
"export": {
"enabled": true,
"libs": {
"path": "http://amcharts.com/lib/3/plugins/export/libs/"
}
}
});
What I have given in the addLabel parameter is not being taken and the label is also not getting shown. Can anybody help me on this?
There is no such property in amCharts addLabel. There is a method, which can be used to add labels to an already existing chart object.
To specify labels in the JSON config of the chart, use allLabels:
"allLabels": [{
"x": 0,
"y": 25,
"text": "Total Tweets= 360"
}]
Using python, is it possible to reconstruct an image from the json representation of a fabric.js canvas?
It's easy to do with Node.js but I am using django so I prefer not having to run a separate node.js server just to create these images to send them to my django server.
No.
I don't see how it's possible without writing Python port of Fabric (or a custom parser+renderer).
Here's why:
JSON data string contains custom representation of various Fabric shapes, which — during parsing and interpretation by Fabric's loadFromJSON — are all loaded and rendered onto canvas. The canvas could then be used to generate an image.
You can parse data in python, since it's just JSON. You can walk over it and analyze it. You'll even be able to "see" the kinds of shapes that need to be loaded onto canvas. But you'll still need the main thing — creating visual representation of each of those shapes.
Unless you do that manually (using some kind of graphics methods in Python; which sounds like a whole lot of work), I don't think there's much else that can be done.
You don't have to run a separate node server. But you do need a node runtime with the modules - 'canvas' and 'fabric' installed. With that done, you can trivially call the nodejs script from your python code
Here is a sample js script which will read the JSON input and generate a PNG output file
var fabric = require('fabric').fabric,
fs = require('fs'),
out = fs.createWriteStream(process.argv[3]);
var canvas = fabric.createCanvasForNode(530, 630);
canvas.loadFromJSON(process.argv[2], function() {
canvas.renderAll();
var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
out.write(chunk);
});
});
And here is how you can call it in your python code
import subprocess
fabric_json = u'{"objects": [{"opacity": 1, "strokeMiterLimit": 10, "isMulticolor": false, "height": 203, "visible": true, "stroke": null, "filters": [], "hexColors": ["#085a68", "#ca350a", "#d8ec73"], "fill": "rgb(0,0,0)", "angle": 0, "fillRule": "nonzero", "flipX": false, "flipY": false, "top": 205.78, "scaleX": 0.46, "scaleY": 0.46, "strokeLineJoin": "miter", "width": 200, "backgroundColor": "", "clipTo": null, "type": "image", "strokeLineCap": "butt", "strokeDashArray": null, "strokeWidth": 1, "originY": "top", "originX": "left", "globalCompositeOperation": "source-over", "designId": 2825, "alignY": "none", "alignX": "none", "shadow": null, "crossOrigin": "", "src": "http://localhost.com/designs/sampleimage.png", "meetOrSlice": "meet", "designFileName": "sampleimage.png", "left": 208.68}], "backgroundImage": {"opacity": 1, "strokeMiterLimit": 10, "height": 630, "visible": true, "stroke": null, "filters": [], "fill": "rgb(0,0,0)", "angle": 0, "fillRule": "nonzero", "flipX": false, "flipY": false, "top": 0, "scaleX": 1, "scaleY": 1, "strokeLineJoin": "miter", "width": 530, "backgroundColor": "", "clipTo": null, "type": "image", "strokeLineCap": "butt", "strokeDashArray": null, "strokeWidth": 1, "originY": "top", "originX": "left", "globalCompositeOperation": "source-over", "alignY": "none", "alignX": "none", "shadow": null, "crossOrigin": "", "src": "http://localhost.com:5000/static/images/fabric/ts_rne_front.png", "meetOrSlice": "meet", "left": 0}, "background": "#bf1515"}'
subprocess.call(["node", "fabricImageGenerator.js", fabric_json, "outputImage.png"])