I am using Highcharts Export Server and its an external server. I am sending a JSON request to it and want to get the image out there on the screen. I have the sample working if I just draw graph on the screen as shown in the fiddle below with the Graph as it looks like.
Normal Chart can be found here
Highcharts.chart('container', {
chart: {
type: 'bar'
},
title: {
text: 'Stacked bar chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
}
},
legend: {
reversed: true
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2],
color: {
pattern: 'https://sampleproject-shivkumarganesh.c9users.io/img/Dots_Large.png',
width: 10,
height: 10
}
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1],
color: {
pattern:'https://sampleproject-shivkumarganesh.c9users.io/img/Grid.png',
width: 10,
height: 10
}
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5],
color: {
pattern:'https://sampleproject-shivkumarganesh.c9users.io/img/Bricks.png',
width: 15,
height: 15
}
}]
});
But when I try to host my server to print this using Highcharts Export Server, I get a graph which is nothing but Blank Lines as shown below:-
Edited Code Here with Export Server
$(function () {
$("#b").click(testPOST);
var exportUrl = 'http://export.highcharts.com/';
function testPOST() {
var optionsStr = '{"chart":{"type":"bar"},"title":{"text":"Stacked bar chart"},"xAxis":{"categories":["Apples","Oranges","Pears","Grapes","Bananas"]},"yAxis":{"min":0,"title":{"text":"Total fruit consumption"}},"legend":{"reversed":true},"plotOptions":{"series":{"stacking":"normal"}},"series":[{"name":"John","data":[5,3,4,7,2],"color":{"pattern":"https://sampleproject-shivkumarganesh.c9users.io/img/Dots_Large.png","width":10,"height":10}},{"name":"Jane","data":[2,2,3,2,1],"color":{"pattern":"https://sampleproject-shivkumarganesh.c9users.io/img/Grid.png","width":10,"height":10}},{"name":"Joe","data":[3,4,4,2,5],"color":{"pattern":"https://sampleproject-shivkumarganesh.c9users.io/img/Bricks.png","width":15,"height":15}}]}';
dataString = encodeURI('async=true&type=jpeg&width=400&options=' + optionsStr);
if (window.XDomainRequest) {
var xdr = new XDomainRequest();
xdr.open("post", exportUrl+ '?' + dataString);
xdr.onload = function () {
console.log(xdr.responseText);
$('#container').html('<img src="' + exporturl + xdr.responseText + '"/>');
};
xdr.send();
} else {
$.ajax({
type: 'POST',
data: dataString,
url: exportUrl,
success: function (data) {
console.log('get the file from relative url: ', data);
$('#container').html('<img src="' + exportUrl + data + '"/>');
},
error: function (err) {
debugger;
console.log('error', err.statusText)
}
});
}
}
});
Now, this seems to be weird because I am not able to understand why the export server is not able to render my images that I send a JSON Request.
I have no clue what I should do to make it work and print the use the PNG images to fill the graph. I am doing this in order to print and get the graphs with patterns for people who suffer from color blindness. We need to export it to PDF after getting a png.
NOTE:-
The Stack is as follows:-
Highcharts Export Server
pattern-fill plugin highcharts
Few PNG images
Related
I am trying to update my current highchart that I have to a new chart type, however I am having difficulty doing so.
I have embedded javascript in my page, the following is below
<script>
chart = $(function () {
$('#chart_example').highcharts({
chart: {
type: 'line'
},
title: {
text: 'Traffic'
},
xAxis: {
categories: ['November', 'December', 'January']
},
yAxis: {
title: {
text: 'Views'
}
},
series: [{
name: 'Hello',
data: [50, 30, 60]
}]
});
});
</script>
I have the following two scripts below at the bottom of the page
<script src="http://code.highcharts.com/highcharts.js"></script>
....
<script src="custom_script"></script>
</body>
</html>
Inside the custom script, I want to update the highcharts library from a line graph into a bar graph. I looked at the API and found an update method
that takes in new options. So I tried the following:
$(document).on('click' , '#button' , function() {
var options = new Object();
options.chart = new Object();
options.chart.type = 'bar';
options.chart.renderTo = 'container';
chart.update(options, true);
//the container the chart is in
$('#chart_example').show();
...
However I get
Uncaught TypeError: chart.update is not a function(anonymous function) # custom_script=1:41m.event.dispatch # jquery.min.js:3m.event.add.r.handle # jquery.min.js:3
My thought was that the order of the javascript is wrong but I seem to have the javascript in the right order. My questions are then:
1) Is this chart variable set correctly? My understanding is that a variable that is unset with var is automatically global.
2) What is the cause of this error and how do I fix it so that it updates properly?
Thank you in advance!
http://jsfiddle.net/2j1g200g/29/
var options = {
chart: {
type: 'line',
renderTo: 'chart_example'
},
title: {
text: 'Traffic'
},
xAxis: {
categories: ['November', 'December', 'January']
},
yAxis: {
title: {
text: 'Views'
}
},
series: [{
name: 'Hello',
data: [50, 30, 60]
}]
};
chart = new Highcharts.Chart(options);
options.chart.type = 'bar';
chart = new Highcharts.Chart(options);
Run this, it should get what you want. I included a button for demonstration.
chartOptions = {
chart: {
type: 'line'
},
title: {
text: 'Traffic'
},
xAxis: {
categories: ['November', 'December', 'January']
},
yAxis: {
title: {
text: 'Views'
}
},
series: [{
name: 'Hello',
data: [50, 30, 60]
}]
};
$('#chart_example').highcharts(chartOptions);
$(document).on('click' , '#button' , function() {
chartOptions.chart.type = 'bar';
$('#chart_example').highcharts(chartOptions);
});
<button id="button">rechart</button>
<div id="chart_example"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
I am trying to prepare a Tornado Chart using the column chart in Highcharts. Here is my fiddle.
My current code is:
$('#container').highcharts({
chart: {
type: 'columnrange',
inverted: true
},
title: {
text: 'Net Sales'
},
subtitle: {
text: 'MM $'
},
xAxis: {
categories: ['Annual Revenue', 'Number of Years', 'Annual Costs']
},
yAxis: {
title: {
text: 'MM $'
}
},
plotOptions: {
columnrange: {
dataLabels: {
enabled: true,
formatter: function () {
return this.y;
}
}
},
scatter:{
marker:{
symbol:'line',
lineWidth:11,
radius:8,
lineColor:'#f00'
}
}
},
legend: {
enabled: false
},
series: [{
name: 'Temperatures',
data: [
[12.15, 46.86],
[15.45, 42.28],
[27.77, 31.24]
]
},
{
name:'Base',type: 'scatter',data:[120],
}]
});
The problem is that the last series (Annual Costs) does not show, as it is in reversed order. Also, I'd like the Tornado Chart to look more like this:
Note that the labels in this chart are different from the actual values plotted. Also note that the bar in the center - in the example code, there would be a vertical line at 29.5. I would also like to support a combined uncertainty bar like the one at the bottom. Any suggestions would be greatly appreciated.
Your last bat is not showing, because first number is lower than second, see: http://jsfiddle.net/kErPt/1/
If you want to display another values at labels, then add that info first. Example:
data: [{
low: 12,
high: 15,
lowLabel: 35,
highLabel: 46
}, {
low: 2,
high: 35,
lowLabel: 15,
highLabel: 26
} ... ]
And then use dataLabels.formatter for series.
To add vertical line use plotLines.
I'm not sure what is the last bar called 'combined uncertainty'.
I've used Highcharts with separate series (thanks jlbriggs) to create a Tornado Chart: http://jsfiddle.net/uRjBp/
var baseValue = 29.5;
var outputTitle = "Net Sales";
var chart = new Highcharts.Chart({
chart: {
renderTo:'container',
//type:'column'
//type:'area'
//type:'scatter'
//type:'bubble'
},
credits: {},
exporting: {},
legend: {},
title: {
text: outputTitle
},
subtitle: {
text: "MM $"
},
tooltip: {
formatter: function() {
var msg = "";
var index = this.series.chart.xAxis[0].categories.indexOf(this.x);
var low = round(this.series.chart.series[0].data[index].y+baseValue);
var high = round(this.series.chart.series[1].data[index].y+baseValue);
if (this.x === "Combined Uncertainty") {
msg = "Combined Uncertainty in "+outputTitle+": "+low+" to "+high;
} else {
var lowLabel = this.series.chart.series[0].data[index].label;
var highLabel = this.series.chart.series[1].data[index].label;
msg = '<b>'+outputTitle+'</b> goes from '+ low +' to '+ high+'<br/> when '+this.x +
' goes from <br/> '+lowLabel+" to "+highLabel;
}
return msg;
}
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
formatter: function () {
var index = this.series.chart.xAxis[0].categories.indexOf(this.x);
if (this.series.userOptions.labels === undefined) {
return this.y+baseValue;
}
return this.key === "Combined Uncertainty" ? "":this.series.userOptions.labels[index];
}
}
}
},
xAxis: {
title: {
text: 'Factor'
},
allowDecimals:false,
categories: ['Annual Revenue', 'Number of Years', 'Annual Costs', 'Combined Uncertainty']
},
yAxis: {
title: {
text: 'MM $'
},
labels: {
formatter:function() {
return this.value+baseValue;
}
}
},
series:[{
name: 'Low',
grouping:false,
type:'bar',
data:[{y:12.15-baseValue, label:10},{y:15.45-baseValue, label:1},{y:31.25-baseValue, label:2},{y:12.15-baseValue, color:'#99CCFF', label: ""}],
labels:[10,1,2,]
},{
name: 'High',
grouping:false,
type:'bar',
data:[{y:46.86-baseValue, label:30},{y:42.28-baseValue, label:3},{y:27.77-baseValue, label:4},{y:46.86-baseValue, color:'#99CCFF', label:""}],
labels:[30,3,4,]
},
{
name: 'Median',
type: 'scatter',
data: [null,null, null,27-baseValue],
marker: {
lineWidth: 2,
lineColor: Highcharts.getOptions().colors[3],
fillColor: 'white'
}
}]
});
function round(num) {
return Math.round(num*100)/100;
}
usually, this kind of chart is done using a separate series for the left and right portions
One way to do this is by setting one set of data as negative numbers, and then using the formatters to make the axis labels, datalabels, and tooltips display the absolute values
example:
http://jsfiddle.net/jlbriggs/yPLVP/68/
UPDATE:
to show a line as in your original chart, you can extend the marker symbols to include a line type, and use a scatter series to draw that point:
http://jsfiddle.net/jlbriggs/yPLVP/69/
If you don't want to have the extra code for the line marker type, you could use any of the other existing marker symbols for the scatter series.
Server is sending back data like this:
{"barData":
[
{"Accepted":[0,0,0]},
{"Rejected":[0,0,0]},
{"In_Process":[0,1,0]}]
}
In the browser, it shows up as such:
My perhaps (and very likely) incorrect belief was that this was the correct structure to populate a Highcharts stacked bar chart as seen here:
Example Stacked Bar in jsFiddle
The example in the documentation shows a fixed data set that appears like this:
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
This is what I was attempting to emulate. So, at the end of all that, I get a zero plot. My Javascript looks like this:
$.ajax({
url : 'http://localhost:8080/afta/report/transfersbynetwork',
success : function(point) {
data = [];
$.each(point.barData, function(itemNo, item) {
data.push([ item[0], parseInt(item[1][0]), parseInt(item[1][1]), parseInt(item[1][2])]);
});
barchart = new Highcharts.Chart(baroptions);
baroptions.series[0].data = data;
},
cache : false
});
So where did I bone this up? I'm getting no plot and am quite convinced the problem is either in my presentation of the data from the server (possible) or in the javascript that's parsing the data structure and loading the series (highly likely).
Any insight would be appreciated.
Based on your structure, you need to change your function to process the data:
$(function () {
var point = {
"barData": [{
"Accepted": [1, 2, 3]
}, {
"Rejected": [3, 4, 5]
}, {
"In_Process": [0, 1, 0]
}]
},
data = [];
$.each(point.barData, function (itemNo, item) {
for (var prop in item) {
data.push({
name: prop,
data: [parseInt(item[prop][0]), parseInt(item[prop][1]), parseInt(item[prop][2])]
});
}
});
$('#container').highcharts({
chart: {
type: 'bar'
},
title: {
text: 'Stacked bar chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
}
},
legend: {
backgroundColor: '#FFFFFF',
reversed: true
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: data
});
});
http://jsfiddle.net/9jVJb/
I was wondering if anyone knew of jsfiddle examples where stacked bar graphs with multiple values on a single point were changed after their creation. I've seen plenty of examples using setData for single points on a series, but none for multiple.
I currently have the following graphs and would like to put multiple values on each point.
window.jQuery(function () {
//var opportunities_by_month_chart;
opportunities_by_month_chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: 'Pipeline By Month By Outcome'
},
subtitle: {
text: ''
},
xAxis: {
categories: ['test', 'test2']
},
yAxis: {
min: 0,
title: {
text: 'Opportunity size in £'
}
},
tooltip: {
formatter: function () {
return 'Month: ' + this.x + '<br/>' +
this.series.name + ': £' + this.y + '<br/>' +
'Total: £' + this.point.stackTotal;
}
},
plotOptions: {
series: {
stacking: 'normal'
}
},
credits: {
enabled: false
},
series: [{
name: 'Closed Won',
data: [],
color: 'green'
}, {
name: 'Closed Postponed',
data: [],
color: 'orange'
}, {
name: 'Closed Lost',
data: [],
color: 'red'
}, {
name: 'Other',
data: [],
color: 'blue'
}
]
});
});
http://jsfiddle.net/9FyGX/2/
If someone could point to an example or add an example to the jsfiddle it would make my day :D
As you said
chart.series[0].setData([1, 2, 3, 4], true);
chart.series[1].setData([2, 3, 4], true);
will work. However, the last parameter (true) tells highcharts to redraw the chart. Therefore it's more effecient to call the fist setData with false, and only redraw once you've finished adding the data.
chart.series[0].setData([1, 2, 3, 4], false);
chart.series[1].setData([2, 3, 4], true);
With highcharts, you have a built-in button to download the current chart (example: http://www.highcharts.com/demo/, this button: ). You can save it as PNG, JPEG, PDF or SVG.
What I'd like to do is to create a link that saves the image on the server, instead of downloading it. How could I do that ?
I suppose that I have to modify the exportChart function in the exporting.src.js file. It looks like this (but I don't know javascript enough to do that) :
exportChart: function (options, chartOptions) {
var form,
chart = this,
svg = chart.getSVG(chartOptions);
// merge the options
options = merge(chart.options.exporting, options);
// create the form
form = createElement('form', {
method: 'post',
action: options.url
}, {
display: NONE
}, doc.body);
// add the values
each(['filename', 'type', 'width', 'svg'], function (name) {
createElement('input', {
type: HIDDEN,
name: name,
value: {
filename: options.filename || 'chart',
type: options.type,
width: options.width,
svg: svg
}[name]
}, null, form);
});
// submit
form.submit();
// clean up
discardElement(form);
},
It could be done really easy with PhantomJS. You can render Highchart chart and save it to SVG, PNG, JPEG or PDF. The example below renders a demo Highcharts diagram to SVG and PDF at the same time:
var system = require('system');
var page = require('webpage').create();
var fs = require('fs');
// load JS libraries
page.injectJs("js/jquery.min.js");
page.injectJs("js/highcharts/highcharts.js");
page.injectJs("js/highcharts/exporting.js");
// chart demo
var args = {
width: 600,
height: 500
};
var svg = page.evaluate(function(opt){
$('body').prepend('<div id="container"></div>');
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
width: opt.width,
height: opt.height
},
exporting: {
enabled: false
},
title: {
text: 'Combination chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Bananas', 'Plums']
},
yAxis: {
title: {
text: 'Y-values'
}
},
labels: {
items: [{
html: 'Total fruit consumption',
style: {
left: '40px',
top: '8px',
color: 'black'
}
}]
},
plotOptions: {
line: {
dataLabels: {
enabled: true
},
enableMouseTracking: false
},
series: {
enableMouseTracking: false,
shadow: false,
animation: false
}
},
series: [{
type: 'column',
name: 'Andrii',
data: [3, 2, 1, 3, 4]
}, {
type: 'column',
name: 'Fabian',
data: [2, 3, 5, 7, 6]
}, {
type: 'column',
name: 'Joan',
data: [4, 3, 3, 9, 0]
}, {
type: 'spline',
name: 'Average',
data: [3, 2.67, 3, 6.33, 3.33],
marker: {
lineWidth: 2,
lineColor: 'white'
}
}, {
type: 'pie',
name: 'Total consumption',
data: [{
name: 'Andrii',
y: 13,
color: '#4572A7'
}, {
name: 'Fabian',
y: 23,
color: '#AA4643'
}, {
name: 'Joan',
y: 19,
color: '#89A54E'
}],
center: [100, 80],
size: 100,
showInLegend: false,
dataLabels: {
enabled: false
}
}]
});
return chart.getSVG();
}, args);
// Saving SVG to a file
fs.write("demo.svg", svg);
// Saving diagram as PDF
page.render('demo.pdf');
phantom.exit();
If you save the code as demo.js, then just run bin/phantomjs demo.js to generate demo.svg and demo.pdf
I just implement this using Nobita's method. I was creating a survey that showed the user's results in a chart, uploaded the image to my server and then sent out an email with the image in it. Here's a few things to note.
I had to make a few updates to the highcharts/exporting-server/index.php file which are the following:
I changed the directory from "temp" to something else and just note that it is in 4 different locations.
I had to change shell_exec() adding "-XX:MaxHeapSize=256m" because it was giving me an error:
$output = shell_exec("java -XX:MaxHeapSize=256m -jar ". BATIK_PATH ." $typeString -d $outfile $width /mypathhere/results/$tempName.svg");
If you want it to download that image you can leave the following alone:
header("Content-Disposition: attachment; filename=$filename.$ext");
header("Content-Type: $type");
echo file_get_contents($outfile);
But, I changed this because I wanted to send back the path to the image, so I deleted the above and replace this with the image path (Note that I'm just using the temporary name.):
echo "/mypathhere/results/$tempName.$ext";
Also, this file is deleting the svg file and also the new file you made. You need to remove the code that deletes the file:
unlink($outfile);
And you can also delete the line before it if you want to keep the svg file.
Make sure to include highcharts/js/modules/exporting.js
Then, in your JS you can do something like the following:
var chart = new Highcharts.Chart();
var imageURL = '';
var svg = chart.getSVG();
var dataString = 'type=image/jpeg&filename=results&width=500&svg='+svg;
$.ajax({
type: 'POST',
data: dataString,
url: '/src/js/highcharts/exporting-server/',
async: false,
success: function(data){
imageURL = data;
}
});
The URL you are posting to is the new version of the /exporting-server/index.php. Then, you can use the imageURL however you like.
I haven't done that before, but I believe you want to play with the index.php file located in the exporting-server folder.
By default Highcharts provides (for free) a web service but you can modify that and create your own web service for exporting, or do whatever you want with the chart. Look at these instructions which can be found here Export module:
"If you want to set up this web service on your own server, the index.php file that handles the POST is supplied in the download package inside the /exporting-server directory.
Make sure that PHP and Java is installed on your server.
Upload the index.php file from the /exporting-server directory in
the download package to your server.
In your FTP program, create directory called temp in the same
directory as index.php and chmod this new directory to 777
(Linux/Unix servers only).
Download Batik from http://xmlgraphics.apache.org/batik/#download.
Find the binary distribution for your version of jre
Upload batik-rasterizer.jar and the entire lib directory to a
location on your web server. In the options in the top of the
index.php file, set the path to batik-rasterier.jar.
In your chart options, set the exporting.url option to match your
PHP file location. "
You can try this
var chart = $('#yourchart').highcharts();
svg = chart.getSVG();
var base_image = new Image();
svg = "data:image/svg+xml,"+svg;
base_image.src = svg;
$('#mock').attr('src', svg);
Take html of Mock and send to DB or save only the binary code .
Save highchart as binary image