I am using jqPlot to display many graphs on some webpages. I am wanting to be able to save these graphs to an image file.
What is the best way to do this? Is it possible to have a right click menu option on the graph that enables the graph to be saved to an image file?
Here is some code for one of my graphs:
var plotCogsLineGraph = $.jqplot('FinancialsLineGraph', [[30,31,34,40,45], [34,38,31,42,38]],
{
axes:
{
xaxis:
{
ticks: ['5','4','3','2','1']
},
yaxis:
{
label:'%',
pad: 1.05,
ticks: ['0','15','30','45','60']
}
},
width: 480, height: 270,
legend:{show:true, location: 's', placement: 'insideGrid', renderer: $.jqplot.EnhancedLegendRenderer},
seriesDefaults:
{
rendererOptions: {smooth: true}
},
series:[
{
lineWidth:1,
label:'COGS',
markerOptions: { size:1, style:'dimaond' }
},
{
lineWidth:1,
label:'Wages',
markerOptions: { size: 1, style:"dimaond" }
}
]
}
);
What needs to be added to this above code to enable saving the graph to an image file?
Try this:
$('#FinancialsLineGraph').jqplotSaveImage()
Let's say your plot is drawing in a div with 'plot' id.
You have to apply native jqplotToImageStr({}) function in order to convert the plot to an image.
Then you can fill an other div (with id = 'graphicImage' for example) in order to display this freshly generated image :
var graphicImage = $('#graphicImage');
if(graphicImage.html() == ""){ //If the image was even generated, don't generate it again
var divGraph = $('#plot').jqplotToImageStr({});
var divElem = $('<img/>').attr('src', divGraph);
graphicImage.html(divElem);
}
In order to download the image, you can do something like :
open(divGraph.toDataURL("image/png"));
In my case it doesn't work great as the image downloaded on my computer is corrupted.
If you find a way to save it I'll be great to hear about it.
Anyway, once you have done the first part on this answer (fill the '#graphicImage' div with the image corresponding to jqplot), you can save it thanks to a right click on it...
$('#GraphName').jqplotSaveImage() but aware that if you have applied some custom styles on ticks this won't be saved to image
Related
Following is my resultant chart
Here the value of legends Happy and Very Happy is 0, hence it is overlapping each other and unable to read. So, How can I hide these values and strike through the legends while loading itself like in the below image? And yes, it is a dynamically loaded chart.
Link - Reference Pie Chart
Thanks in advance.
I am posting this answer hoping that, it will be helpful for someone later. You can also post a better solution if found.
After some deep diving into the library the files, I realised that is there are no direct answers to my question. But we can achieve that by emptying the label text in case of 0 data values.
For that, we must edit the chart options as follows,
public pieChartOptions: ChartOptions = {
responsive: true,
legend: {
position: 'top',
},
plugins: {
datalabels: {
formatter: (value, ctx) => {
const label = ctx.chart.data.labels[ctx.dataIndex];
if (ctx.dataset.data[ctx.dataIndex] > 0)
return label + " : " + ctx.dataset.data[ctx.dataIndex];
else
return "" // retun empty if the data for label is empty
},
}
},
showLines: true,
spanGaps: true,
cutoutPercentage: 1,
rotation: 15, // rotate the chart
};
Here in the function returns empty value in case the data for the corresponding label is 0. Also I rotate the chart 15deg to make the labels horizontal align in most cases.
Reference - Chart.js documentation
Hence I achieved a better view to the user and the overlapping issues are resolved. Thanks.
For my graph, I have a single y-axis (y1), and I am trying to add a second axis (y2) which is a scaled version of y1.
Simply put, is it possible to do a graph like this. But I want a second axis, with the same scaling ratio, but in different units (i.e. that is multiplied by some k).
I have tried to just change the label on the yAxis:
` labels: {
format: '$ {value* price} ',
style: {
color: Highcharts.getOptions().colors[0]
}
},`
But this hacky way does not seem to work for me.
In my case, I have a graph of percent change on y1, is it possible to put the price on y2?
I do not want to add another set of lines since I am already using 10, which would mean I would need 20 lines in total
Any help would be greatly appreciated!
You need to link the second axis to the first by linkedTo property and use formatter function to display some custom scale:
yAxis: [{}, {
opposite: true,
labels: {
formatter: function() {
return this.value * 1000
}
},
linkedTo: 0
}]
Live demo: http://jsfiddle.net/BlackLabel/j83pghta/
API Reference:
https://api.highcharts.com/highcharts/yAxis.linkedTo
https://api.highcharts.com/highcharts/yAxis.labels.formatter
Good afternoon, I'm putting together a chart that uses Highcharts stackLabels, it's exactly the same as this: JSFiddle however I do not want it to display the sum of the column values, I want it to appear item by item one on top of the other, same as the print I simulated below:
In order to set your stackLabels as you expecting, you need to use stackLabels.formatter function to calculate the labels values manually.
Next thing you've to do is make a little shifting on the labels. You are able to do it by stackLabels.y field.
At the end, don't forget about the stackLabels.useHTML parameter set equal to true. It makes the <span> and </br> elements will appear correctly. Please take a look at code below:
yAxis: {
stackLabels: {
style: {
color: 'red'
},
enabled: true,
useHTML: true,
formatter: function() {
var firstLabel = Math.round((this.points[0][1] - this.points[0][0]) * 10) / 10,
secondLabel = this.points[0][0]
return `<span>${firstLabel}</span></br>
<span>${secondLabel}</span>`
},
y: -15
}
}
You can read more about parameters mentioned above here:
https://api.highcharts.com/highcharts/yAxis.stackLabels.formatter
https://api.highcharts.com/highcharts/yAxis.stackLabels.y
https://api.highcharts.com/highcharts/yAxis.stackLabels.useHTML
Live example: http://jsfiddle.net/r01nkgyn/
I am using Primefaces 6 for my companys charting needs, which relies on jQplot.
For a project, I am trying to overlay a line chart on a stacked bar chart with negative values, to obtain something like this:
The problem is that when I try to add a linechartseries to the same model as the two barchartseries , the linechart becomes a part of the stack when setting setStacked(true); on the model, because Primefaces seems to not allow individual disabling of stacking on series, only per model. So I end up with this when rendering the chart with
<p:chart type="bar" model="#{backingBean.cartesianChartModel}"/>
After some investigation I have notoced that jQplot is capable of disabling Stacking on individual series by passing disableStack : true in the JS options, so the question is if it's posssible to override this in some way on the rendered page,either via PF or via some JS hack? I feel that using the extender only apples to the entire model?
Related issues: Disable individual stacking
By pouring through the documentation I found a solution to the problem, if not the question:
It seems that Primefaces allows for individual series to be excempt from the stack in the series creation in this version, by passing
LineChartSeries.setDisableStack(true);
Simple as that.
I guess it may be possible. I used the extender functionality for some jqPlot hacks in the past.
In my case, for example, I had a Donut Chart defined with an extender function as follows:
private void createDonutModel() {
donutModel = new DonutChartModel();
donutModel.setLegendPosition("s");
donutModel.setLegendPlacement(LegendPlacement.OUTSIDE);
donutModel.setSliceMargin(4);
donutModel.setDataFormat("value");
donutModel.setShadow(false);
donutModel.setExtender("donutExtender");
donutModel.setSeriesColors("B81C40, FFA600, 79B54A");
}
The corresponding javascript was doing some changes to the jqPlot:
/**
* Customized jqPlot JQuery layout of the Donut Chart for Status Dashboard.
*/
function donutExtender() {
this.cfg.seriesDefaults = {
// make this a donut chart.
renderer:$.jqplot.DonutRenderer,
rendererOptions:{
thickness: 26,
ringMargin: 0,
fill: true,
padding: 0,
sliceMargin: 4,
// Pies and donuts can start at any arbitrary angle.
startAngle: -90,
showDataLabels: false,
// By default, data labels show the percentage of the donut/pie.
// You can show the data 'value' or data 'label' instead, or 'percent'
dataLabels: 'value',
shadow: false
}
}
this.cfg.gridPadding = {
top: 0, right: 0, bottom: 0, left: 0
}
this.cfg.legend = {
show: false
}
this.cfg.grid = { drawBorder: false,
shadow: false,
background: "transparent"
};
}
So you may try something like this in your case ?
Leave the extension configuration of your series empty, except for the one you are interested in...
function chartExtender() {
this.cfg.series = [
{ //...
},
{ // ...
},
{
disableStack: true
}
]
}
Worth having a shot ...
Im rendering graph by morris js. Im using data from mysql database by JSON.
Everything works fine, but I would like to add one more feature to the graph. (change dot color if there is something in buy action).
My JSON:
[{"longdate":"2014-08-20
18:20:01","price":"1620","action":"buy"},{"longdate":"2014-08-20
18:40:01","price":"1640","action":""},{"longdate":"2014-08-20
19:00:01","price":"1620","action":""}]
So I would like to change dot color for values with buy action.
My code for graph:
$.getJSON('results.json', function(day_data) {
Morris.Line({
element: 'graph',
data: day_data,
xkey: 'longdate',
ykeys: ['price'],
labels: ['Cena'],
lineColors: lineColor,
pointSize: 0,
hoverCallback: function(index, options, content) {
var date = "<b><font color='black'>Data: "+day_data[index]['longdate']+"</font></b><br>";
var param1 = "<font color='"+lineColor[0]+"'>Cena - "+day_data[index]['price']+"</font><br>";
return date+param1;
},
xLabelFormat : function (x) {
return changeDateFormat(x);
}
/*My TRIAL
if(action == 'buy'){
pointSize: 4,
lineColors: green,
}
*/
});
});
So my code doesnt work, how can I make this working?
Judging from the documentation for the line chart, this library is not capable of doing what you are asking "out of the box" (meaning, without modification).
You could always fork the github project and add this capability. If you are not interested or able to do that, then you'll probably need to choose a different charting library.