Dojo Chart to PDF conversion in IE11 - charts

PDF Outputs
I am new to DOJO charts and in one of the requirement, we have to convert Dojo Chart to PDF.
To achieve this we have used "JSPDF" and "html2canvas" libraries.
It is working fine in Google Chrome and not in IE11.
Kindly suggest.
Regards,
Byreddy
Here is my code....
PDF Test
<div data-dojo-type="dojox.charting.widget.Chart" id="chart1" style="width: 600px; height: 400px; background-color:white;"></div>
<div id="chart1SelectableLegend"></div>
<button id="pdfButton" onclick="convertPDF()">DownloadPDF</button>
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.8/dojo/dojo.js" data-dojo-config="isDebug:true, async:true"></script>
<script>
require(["dojox/charting/Chart",
"dojox/charting/plot2d/Lines",
"dojox/charting/axis2d/Default",
"dojox/charting/plot2d/StackedColumns",
"dojox/charting/action2d/Tooltip",
"dojo/ready",
"dojox/charting/widget/SelectableLegend", "dojox/gfx/utils",
],
function (Chart, Lines, Default, StackedColumns, Tooltip, ready, SelectableLegend, Utils) {
var chart1 = new Chart("chart1");
chart1.title = "stacked chart";
chart1.addPlot("stackedColumnsPlot", {
type: StackedColumns,
gap: 6,
lines: true,
areas: true,
markers: true,
labels: true,
labelStyle: "inside",
tension: "2"
});
chart1.addAxis("x", {
dropLabels: false,
labelSizeChange: true,
rotation: -20,
majorTicks: true,
majorTickStep: 1,
minorTicks: false,
font: "normal normal bold 12px Tahoma",
fontColor: "black",
labels: [{ "value": 1, "text": "A" }, { "value": 2, "text": "B" }, { "value": 3, "text": "C" }, { "value": 4, "text": "D" }, { "value": 5, "text": "E" }, { "value": 6, "text": "F" }]
});
chart1.addAxis("y", {
title: "Cost",
fixLower: "major",
fixUpper: "major",
includeZero: true,
majorTickStep: 500,
max: 1500,
vertical: true
});
chart1.addSeries("AC", [300, 500, 500, 600, 300, 280],
{
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF",
},
fill: "#FFAEAE "
});
chart1.addSeries("TV", [244, 301, 699, 620, 820, 837], {
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF"
},
fill: "#FFEC94"
});
chart1.addSeries("ACCE", [500, 100, 100, 100, 200, 250], {
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF"
},
fill: "#B4D8E7"
});
chart1.addSeries("OTHER", [100, 150, 100, 700, 700, 0, 800, 300, 300], {
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF"
},
fill: "#56BAEC"
});
chart1.render();
new SelectableLegend({
chart: chart1,
horizontal: true,
align: top
}, "chart1SelectableLegend");
});
</script>
<script>
function convertPDF() {
var pdf = new jsPDF('l', 'pt', 'letter');
html2canvas(document.getElementById('chart1'), {
//proxy: "https://html2canvas.appspot.com/query",
//useCORS: true,
onrendered: function (canvas) {
var img = canvas.toDataURL("image/jpeg");
pdf.addImage(canvas, 'JPEG', 15, 15);
pdf.save('PDFTest.pdf');
}
});
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.debug.js"></script>
<script async="" src="https://cdn.rawgit.com/eligrey/FileSaver.js/62d219a0fac54b94cd4f230e7bfc55aa3f8dcfa4/FileSaver.js"></script>
<script src="JSRefs/html2canvas_0.5.0-alpha1.js"></script>

Here is the working sample, make a note of the listed important things in the code, which made the difference.
gfxRenderer: "canvas"
htmlLabels: false,
Below is the working code along with Tooltip functionality.
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.16/dijit/themes/claro/claro.css">
<script>
dojoConfig = {
parseOnLoad: true, // enables declarative chart creation
gfxRenderer: "canvas" // canvas is first priority
};
</script>
<script src="https://js.arcgis.com/3.16/"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.debug.js"></script>
<script src="html2canvas.js"></script>
<script>
function convertPDF() {
var pdf = new jsPDF('l', 'pt', 'letter');
html2canvas(document.getElementById('chart1'), {
onrendered: function (canvas) {
var img = canvas.toDataURL("image/png");
pdf.addImage(img, 'PNG', 15, 15);
pdf.save('PDFTest.pdf');
}
});
}
</script>
<script>
require([
"dojox/charting/Chart",
"dojox/charting/plot2d/Lines",
"dojox/charting/axis2d/Default",
"dojox/charting/plot2d/StackedColumns",
"dojox/charting/action2d/Tooltip",
"dojox/charting/widget/SelectableLegend",
"dojox/gfx/utils",
"dojo/ready",
"dojo/domReady!"
], function (
Chart,
Lines,
Default,
StackedColumns,
Tooltip,
SelectableLegend,
Utils,
ready
) {
var chart1 = new Chart("chart1");
chart1.htmlLabels = false;
chart1.title = "Stacked Chart";
chart1.addPlot("stackedColumnsPlot", {
htmlLabels: false,
type: StackedColumns,
gap: 5,
lines: true,
areas: true,
markers: true,
labels: true,
labelOffset: -10,
labelStyle: "default",
tension: "2"
});
chart1.addAxis("x", {
dropLabels: false,
labelSizeChange: true,
rotation: -20,
majorTicks: true,
majorTickStep: 1,
minorTicks: false,
font: "normal normal bold 12px Tahoma",
fontColor: "black",
labels: [
{ "value": 1, "text": "A" },
{ "value": 2, "text": "B" },
{ "value": 3, "text": "C" },
{ "value": 4, "text": "D" },
{ "value": 5, "text": "E" },
{ "value": 6, "text": "F" }
]
});
chart1.addAxis("y", {
title: "Cost",
fixLower: "major",
fixUpper: "major",
includeZero: true,
majorTickStep: 500,
max: 1500,
vertical: true
});
chart1.addSeries("AC", [300, 500, 500, 600, 300, 280], {
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF"
},
fill: "#FFAEAE "
});
chart1.addSeries("TV", [244, 301, 699, 620, 820, 837], {
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF"
},
fill: "#FFEC94"
});
chart1.addSeries("ACCE", [500, 100, 100, 100, 200, 250], {
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF"
},
fill: "#B4D8E7"
});
chart1.addSeries("OTHER", [100, 150, 100, 700, 700, 80], {
plot: "stackedColumnsPlot",
stroke: {
color: "#FFFFFF"
},
fill: "#56BAEC"
});
new Tooltip(chart1, "stackedColumnsPlot", {
text: function(chartItem) {
// console.debug(chartItem);
//return "Rating: " + chartItem.run.data[chartItem.index] + "; Total Value: " + chartItem.y;
// return "Comparision Rating: " + chartItem.y;
return "Value: " + chartItem.run.data[chartItem.index] + "; Stacked Value: " + chartItem.y;
}
});
chart1.render();
new SelectableLegend({
chart: chart1,
horizontal: true,
align: top
}, "chart1SelectableLegend");
});
</script>
</head>
<body class="claro">
<div id="chart1" style="width: 600px; height: 400px;"></div>
<div id="chart1SelectableLegend"></div>
<button id="pdfButton" onclick="convertPDF()">DownloadPDF</button>
</body>
</html>

Related

Echarts 4 graph plot: specify symbol per category

I am trying to create a graph plot in Echarts 4, where each node belongs to one of two categories: https://codepen.io/autarkie/pen/LqqZjM:
var nodes = [{
"id": 1,
"category": 1
}, {
"id": 2,
"category": 0
}, {
"id": 3,
"category": 1
}, {
"id": 4,
"category": 0
}];
var links = [{
"source": "3",
"target": "1"
}, {
"source": "3",
"target": "2"
}, {
"source": "1",
"target": "2"
}, {
"source": "2",
"target": "4"
}];
var myChart = echarts.init(document.getElementById('chart'));
var option = {
backgroundColor: new echarts.graphic.RadialGradient(0.4, 0.4, 0.7, [{
offset: 0,
color: '#162436'
}, {
offset: 1,
color: '#000'
}]),
legend: {
data: ["Type 1", "Type 2"],
textStyle: {
color: '#fff'
},
icon: 'circle',
type: 'scroll',
orient: 'vertical',
left: 10,
top: 20,
bottom: 20,
itemWidth: 10,
itemHeight: 10
},
animationDurationUpdate: 300,
animationEasingUpdate: 'quinticInOut',
series: [{
type: 'graph',
layout: 'force',
// symbol: 'rect',
//symbolSize: 10,
lineStyle: {
normal: {
curveness: 0.1
}
},
roam: true,
focusNodeAdjacency: true,
legendHoverLink: true,
draggable: true,
force: {
repulsion: 30,
gravity: 0.03,
edgeLength: 50,
layoutAnimation: true
},
data: nodes,
links: links,
categories: [{
name: 'Type 1',
symbol: 'diamond', // !!! DOES NOT WORK !!!
symbolSize: 30, // !!! DOES NOT WORK !!!
itemStyle: {
color: '#79d2a6'
}
},
{
name: 'Type 2',
symbol: "rect", // DOES NOT WORK
symbolSize: 20, // DOES NOT WORK
itemStyle: {
color: '#ff9900'
}
}
],
}]
};
myChart.setOption(option);
Each category should have its own symbol. I know it is possible to specify the symbol for each node separately, like so:
var node_shaped = [{
"id": 1,
"symbol": "rect",
"category": 1
}]
but it this is quite inelegant. Echarts documentation (https://ecomfe.github.io/echarts-doc/public/en/option.html#series-graph.categories.symbol) specifies the option to include a symbol per category, like in the code above. However, that option has no effect whatsoever on the node shapes. Instead, the default circle shape is used. It is possible to change category color using a similar category-wide option, so I am at loss as to why the shape specification doesn't work. Thanks for taking a look.

Google Column Graph Single Date and value showing as multiple adjucent bars

Data Table structure is as follows
{
"cols": [
{
"id": "",
"label": "Date",
"pattern": "",
"type": "date"
},
{
"id": "Col1",
"label": "Col1 Label",
"pattern": "",
"type": "number"
}
],
"rows": [
{
"c": [
{
"v": "Date(2017, 5, 27)"
},
{
"v": 213
}
]
}
]
}
H Axis options
hAxis: {
slantedText: true, slantedTextAngle: 35,
titleTextStyle: {bold: false, fontSize: 11, color: '#610B38'},
textStyle: {
bold: true, fontSize: 8, color: '#4d4d4d'
},
maxAlternation: 1,
showTextEvery: 1,
viewWindowMode : 'maximized',
gridlines:
{
count: 31
},
bar: { groupWidth: 40 }
}
But in the column graph it is displaying multiple adjacent bars looks like time instead of a single date
This issue happening only for single date.
I want to display the column chart as single bar instead of big rectangle.
Any feedback appreciated
recommend setting the min / max values on the viewWindow explicitly
keeping within a day should prevent "column overflow"
viewWindow: {
min: new Date(dateRange.min.getTime() - oneDay),
max: new Date(dateRange.max.getTime() + oneDay)
}
see following working snippet...
google.charts.load('current', {
callback: function () {
drawChart();
$(window).on('resize', drawChart);
},
packages:['corechart']
});
function drawChart() {
var data = new google.visualization.DataTable({
"cols": [
{
"id": "",
"label": "Date",
"pattern": "",
"type": "date"
},
{
"id": "Col1",
"label": "Col1 Label",
"pattern": "",
"type": "number"
}
],
"rows": [
{
"c": [
{
"v": "Date(2017, 5, 27)"
},
{
"v": 213
}
]
}
]
});
var oneDay = (1000 * 60 * 60 * 24);
var dateRange = data.getColumnRange(0);
var chart = new google.visualization.ColumnChart($('.chart')[0]);
chart.draw(data, {
hAxis: {
slantedText: true,
slantedTextAngle: 35,
textStyle: {
bold: true,
fontSize: 8,
color: '#4d4d4d'
},
viewWindow: {
min: new Date(dateRange.min.getTime() - oneDay),
max: new Date(dateRange.max.getTime() + oneDay)
}
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="chart"></div>
not much you can do for the actual size of the column
the release notes from February, 23 2016 mention...
Added options to specify bar.width, bar.gap, bar.group.width (was bar.groupWidth) and bar.group.gap.
but none have ever worked for me when only one row of data...

Q: how to add "fade in" transition effect for Mapbox circle layer

I'm loading points from Geojson in batches and would like to add "fadeIn" effect or animation when the points first appear in Mapbox.
this.map.addLayer({
id: 'points',
type: 'circle',
paint: {
'circle-radius-transition': {duration: 300},
'circle-color': '#F98200',
'circle-stroke-color': '#D23B00',
'circle-stroke-opacity': 0.5,
},
source: 'points',
})
I tried circle-radius-transition but it does not seem to help.
You are on the right track with the paint properties. I think what you need is the circle-opacity-transition.
Follow these steps:
Add the points with 'circle-opacity': 0 as default opacity value
Set the 'circle-opacity-transition' as you wish
After the map is loaded change the layers 'circle-opacity' to 1 and your layer will be faded in.
map.addLayer({
"id": "point",
"source": "point",
"type": "circle",
"paint": {
"circle-radius": 20,
// here we define defaut opacity is zero
"circle-opacity": 0,
"circle-opacity-transition": {duration: 2000},
"circle-color": 'red'
}
});
You can check out this solution here: codepen
Joel's answer was perfect but the timeout has to be places inside the map load function else the circle layer will not be loaded if the map takes more time to load
Checkout the below code snippet
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9lbHN0dWVkbGUiLCJhIjoiY2ltbmI1OWNpMDAxNnV1bWFtMnpqYWJndyJ9.uDWVjgzU7EVS63OuVWSRuQ';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v9', //stylesheet location
center: [7.445683, 46.945966], // starting position
zoom: 9 // starting zoom
});
// the data we'll add as 'points'
var data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"timestamp": "0",
"location-name": "Bern"
},
"geometry": {
"type": "Point",
"coordinates": [7.445683, 46.945966]
}
}]
}
// so if the map loads do the following
map.on('load', function() {
// add the data source with the information for the point
map.addSource('point', {
"type": "geojson",
"data": data
});
map.addLayer({
"id": "point",
"source": "point",
"type": "circle",
"paint": {
"circle-radius": 20,
// here we define defaut opacity is zero
"circle-opacity": 0,
"circle-opacity-transition": {
duration: 1500
},
"circle-color": 'red'
}
});
//Timeout shoud be within the map load function
setTimeout(function() {
map.setPaintProperty('point', 'circle-opacity', 1);
}, 1);
});
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.36.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.36.0/mapbox-gl.css' rel='stylesheet' />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id='map'></div>
</body>
</html>
Unfortuntely the property-transition won't work in some cases, for example, when you want to toggle a layer on hover.
At least, in my case it does not work. This is my code, the elements pop like there's nothing.
map.addLayer({
'id': 'places-details',
'type': 'symbol',
'source': 'places',
'layout': {
'icon-image': '{icon}',
'text-field': '{data}',
'icon-size': .8,
'text-anchor': 'center',
},
'paint': {
'text-color': '#ffffff',
'icon-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1, 0
],
'text-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1, 0
],
"text-opacity-transition": {
"duration": 3000,
"delay": 0
},
"icon-opacity-transition": {
"duration": 300,
"delay": 0
}
},
});

Highcharts Pie Chart dataLabel Options Don't Work With Object Initialization

Here is a jsfiddle example where I cannot get data label values or percentages to display when initializing the chart by passing it options when creating the chart object. Only the point.name is displayed in the label. Seems like you can only get these options to work when you create the entire object at run time using the plotOptions structure.
http://jsfiddle.net/nstvx7wc/7/
$(document).ready(function(){
var options = {
chart: {
renderTo: 'chartdiv',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '{point.name} {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
},
},
title: {
text: ''
},
};
options.series = [{"colorByPoint": "true", "data": [{"y": 0.36, "name": "series1"}, {"y": 0, "name": "series2"}, {"y": 0, "name": "series3"}, {"y": 0.03, "name": "series4"}, {"y": 0.04, "name": "series5"}, {"y": 0.07, "name": "series6"}]}];
options.title.text = "test pie";
options.pie.dataLabels.enabled = 'true';
chartObject = new Highcharts.Chart(options);
});
You 'pie' option was misconfigured. options.pie doesn't exist. It should be placed under series or the plotoptions property;
See this example; http://jsfiddle.net/nstvx7wc/21/
$(document).ready(function() {
var options = {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: 'test pie'
}
};
options.series = [{
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '{point.name} {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
},
"colorByPoint": "true",
"data": [{
"y": 0.36,
"name": "series1"
}, {
"y": 0,
"name": "series2"
}, {
"y": 0,
"name": "series3"
}, {
"y": 0.03,
"name": "series4"
}, {
"y": 0.04,
"name": "series5"
}, {
"y": 0.07,
"name": "series6"
}]
}];
Highcharts.chart('chartdiv', options);
});

How do I reduce the padding around a FusionCharts pie chart?

I would like to have a pie chart fill a square chart area, currently I can't get it to use more than ~50% of the area, there's lots of grey space all around it. I have tried setting the margin and spacing attributes but it makes no difference.
Is there a way to reduce the padding between the pie chart and the grey box?
FusionCharts.ready(function() {
var demographicsChart = new FusionCharts({
type: 'pie3d',
renderAt: 'chart-container',
width: '100%',
height: '100%',
dataFormat: 'json',
dataSource: {
chart: {
paletteColors: "#FFAE00,#1566EC,#82C309",
bgColor: "#ffffff",
use3DLighting: 1,
showShadow: 0,
enableSmartLabels: 0,
startingAngle: 90,
showLabels: 0,
showValues: 0,
showPercentValues: 0,
showLegend: 0,
pieSliceDepth: 20,
pieYScale: 70,
bgcolor: "EEEEEE,FFFFFF",
bgalpha: "100,100",
bgratio: "0,100",
bgangle: "90",
showBorder: 1,
borderColor: 1,
borderColor: "DDDDDD",
borderThickness: 1,
showToolTip: 0,
spacing: [0, 0, 0, 0],
margin: [0, 0, 0, 0],
animation: 0,
width: "100%",
height: "100%",
},
"data": [{
"label": "Not Started",
"value": 13
}, {
"label": "Complete",
"value": 9
}, {
"label": "In Progress",
"value": 33
}]
}
});
demographicsChart.render();
});
body {
padding: 1em;
}
#chart-container {
width: 300px;
height: 300px;
}
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.charts.js"></script>
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.js"></script>
<div id="chart-container">FusionCharts will render here</div>
By default, FusionCharts XT automatically calculates the best fit pie radius for the chart. But if you want to enforce one of your own values, you can use the attribute "pieRadius". The value is a number which represents the outer radius of the chart. It is mentioned in the docs here http://docs.fusioncharts.com/tutorial-attr-pie3d.html.
I have created a fiddle for you with increased radius. Let me know if this helps.
http://jsfiddle.net/subramaniashiva/ZjyJT/7/
FusionCharts.ready(function () {
var demographicsChart = new FusionCharts({
type: 'pie3d',
renderAt: 'chart-container',
width: '100%',
height: '100%',
dataFormat: 'json',
dataSource: {
chart: {
paletteColors: "#FFAE00,#1566EC,#82C309",
bgColor: "#ffffff",
use3DLighting: 1,
showShadow: 0,
enableSmartLabels: 0,
startingAngle: 90,
showLabels: 0,
showValues: 0,
showPercentValues: 0,
showLegend: 0,
pieSliceDepth: 20,
pieYScale: 70,
bgcolor: "EEEEEE,FFFFFF",
bgalpha: "100,100",
bgratio: "0,100",
bgangle: "90",
showBorder: 1,
borderColor: "DDDDDD",
borderThickness: 1,
showToolTip: 0,
animation: 0,
width: "100%",
height: "100%",
pieRadius: 148
},
"data": [{
"label": "Not Started",
"value": 13
}, {
"label": "Complete",
"value": 9
}, {
"label": "In Progress",
"value": 33
}]
}
});
demographicsChart.render();
});
This seems to be only a partial answer. If you want to display the pie values on the chart, there are two problems:
Values cannot be displayed inside the chart. Is there no method for this?
and
Values that displayed outside the chart have a large amount of padding between the value and the chart. Is there any method to reduce that space?