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);
Related
I'm displaying a balance of a bank account over time. My goal is to have individual tool tips that show the balance AND the transaction that the balance change corresponds to.
I know I can format the Y value with a formatter, but after looking for a few hours I can't find a way to add data to each tool tip. For example the first tool tip might change the balance from 100 to 50, the tooltip would say 'credit card payment' the next tool tip might change the balance to 500 and the tool tip would say 'Paycheck'. here's what I'm doing in my options:
series: [{
name: 'Balance',
data: [
{
x: new Date('2018-02-12').getTime(),
y: 76
}, {
x: new Date('2019-02-12').getTime(),
y: 100
},
{
x: new Date('2020-02-12').getTime(),
y: 200
}, {
x: new Date('2021-02-12').getTime(),
y: 300
},
{
x: new Date('2022-02-12').getTime(),
y: 150
}, {
x: new Date('2023-02-12').getTime(),
y: 22
}
]
}],
options: {
chart: {
type: 'line',
stacked: false,
height: 380,
zoom: {
type: 'x',
enabled: true,
autoScaleYaxis: true
},
toolbar: {
autoSelected: 'zoom'
}
},
dataLabels: {
enabled: false
},
markers: {
size: 2,
},
title: {
text: 'Account balance over time',
align: 'left'
},
yaxis: {
labels: {
formatter: function (val) {
return val.balance;
},
},
title: {
text: 'Balance'
},
},
xaxis: {
type: 'datetime',
},
tooltip: {
shared: true,
y: {
formatter: function (val) {
return "$"+val;
}
}
}
},
Here is what the tooltips look like now:
Above the word 'balance' Id like it to say the actual transaction that's changing the balance. I'm wondering if this is possible at all with apex charts.
Have you tried these options from the docs: https://apexcharts.com/docs/options/tooltip/
There is a 'custom' function you can pass to create your own custom html
under the section called 'custom: function || Array of functions'
Here is the codepen they provide.
tooltip: {
custom: function({ series, seriesIndex, dataPointIndex, w }) {
return (
'<div class="arrow_box">' +
"<span>" +
w.globals.labels[dataPointIndex] +
": " +
series[seriesIndex][dataPointIndex] +
"</span>" +
"</div>"
);
}
}
Also, there is the 'formatter: function' where you can just provide a function to the formatter, similar to what you've already done.
I have this fiddle JSfiddle
Here is the reproduced code:
$(function () {
$('#container').highcharts({
chart: {
type: 'bar'
},
xAxis: {
categories: ['Heroku', 'Ruby','Lisp','Javascript','Python','PHP']
},
yAxis: {
categories: ['low','medium','high'],
title: {
text: 'expertise',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
tooltip: {
valueSuffix: ' millions'
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
}
},
series: [{
data: ['low','high','low','medium','medium']
}]
});
});
If you look at the fiddle the yAxis does not render and has a value of for every x category. I've been looking at the highcharts api, but I can't seem to get this right. The code makes sense to me but I'm obviously doing something wrong. Can someone point out why the YAxis is not displaying correctly?
As mentioned in my comment, you need to supply the numeric value of the category, not the category name.
In the case of categories, the numeric value is the array index.
Also, in your case, the way you are trying to plot the values, I would add an empty category at the beginning, otherwise your first category of low gets plotted as 0, which doesn't seem right.
So,
categories: ['low','medium','high']
Becomes
categories: ['','low','medium','high'],
And
data: ['low','high','low','medium','medium']
Becomes
data: [1,3,1,2,2]
Updated fiddle:
http://jsfiddle.net/jlbriggs/k64boexd/3/
Check this fiddle:
http://jsfiddle.net/navjot227/k64boexd/2/
Trick is to utilize the formatter function. You can use a similar formatter function on y-axis labels too if that's desired. Though it seems like you need it for data labels for this problem.
$(function() {
$('#container').highcharts({
chart: {
type: 'bar'
},
xAxis: {
categories: ['Heroku', 'Ruby', 'Lisp', 'Javascript', 'Python', 'PHP']
},
yAxis: {
title: {
text: 'expertise',
align: 'high'
},
labels: {
overflow: 'justify',
}
},
tooltip: {
valueSuffix: ' millions'
},
plotOptions: {
bar: {
dataLabels: {
enabled: true,
formatter: function() {
if (this.y == 0) {
return 'low'
} else if (this.y == 1) {
return 'medium'
} else {
console.log(this.y);
return 'high'
}
}
}
}
},
series: [{
data: [0, 2, 0, 1, 1]
}]
});
});
In my opinion, it is kinda unlikely for a line graph to have a y-axis category, since it speaks more of amount or value. In your case, "low, medium, and high" speaks of ranges, with which a certain value can be assigned to any of it.
Thus, Highcharts accepts series data in numeric form. But you can work around it by setting ['low', 'medium', 'high'] in the category attribute of yAxis, then setting series data as an array of number corresponding to the index of the category, i.e. [0,1,1,2,...] and tweaking the tooltip to display the category instead of the y value using formatter attribute.
Here is the code:
$(function() {
yCategories = ['low', 'medium', 'high'];
$('#container').highcharts({
title: {
text: 'Chart with category axes'
},
xAxis: {
categories: ['Heroku', 'Ruby','Lisp','Javascript','Python','PHP']
},
yAxis: {
categories: yCategories
},
tooltip: {
formatter: function() {
return this.point.category + ': ' + yCategories[this.y];
}
},
series: [{
data: [0, 1, 2, 2, 1]
}]
});
});
Here is a working example : JSFiddle
I would like to be able to toggle between my groupings, (time/priority). I have a stacked column chart. there is a option to do this example. But it appears that it may only work with data already in a table, and I am bringing in my data as JSON.
my javascript is:
var chart_ops_support_times = new Highcharts.Chart({
chart: {
renderTo: 'chart_ops_support_times',
type: 'column'
},
title: {
text: '',
align: 'left'
},
subtitle: {
text: ' '
},
xAxis: {
categories: [
'one hour','2 hours','4 hours',
'8 hours','one day','2 days',
'one week','> one week'
]
},
yAxis: {
min: 0,
title: {
text: 'counts'
}
},
legend: {
align: 'left',
verticalAlign: 'top',
floating: true,
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
symbolHeight: 10,
symbolWidth: 10
},
tooltip: {
formatter: function () {
return "<b>" + this.x + "</b><br/>" +
this.series.name + ': ' + this.y + "<br/>" +
'Total: ' + this.point.stackTotal;
}
},
plotOptions: {
column: {
stacking: 'normal'
}
},
credits: {
enabled: false
},
exporting: {
enabled: false
},
series: data
});
Data module won't work with JSON.
The Data module provides options for loading data from external sources, like CSV files, HTML tables or Google Spreadsheets, in a convenient way, using a declarative options set.
(http://www.highcharts.com/docs/working-with-data/data-module)
Instead of using data module for this, you could parse your data from JSON to be used one way or another.
Other option is to create hidden HTML table with data from JSON and later use Highcharts with data module and use table.
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.
When I create a stacking bar chart, the rightmost 'box' doesn't have the border drawn on the right hand side.
Is there an option or something that I can set in Highcharts to force the white border line to be drawn around the 75% box in the image seen below?
Here is a link to the jsfiddle I used for testing:
http://jsfiddle.net/zKgsF/
Please note: Setting the borderWidth property to higher than 1 works in displaying, but the rightmost border is much thinner than the others. See the image below.
Here is the javascript for the chart:
$(function () {
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
backgroundColor: 'rgba(0,0,0,.3)',
margin: [15,6,15,15],
},
xAxis: {
categories: ['']
},
credits: {
enabled: false
},
yAxis: {
gridLineColor: "#FF0000",
labels:
{
align: 'right',
formatter: function()
{
return this.value + "%";
}
},
},
tooltip: {
formatter: function()
{
return "<b>" + this.series.name + '</b>: ' + this.y + ' (' + Math.round(this.percentage,1) + "%)";
}
},
plotOptions: {
bar: {
animation: false,
stacking: 'percent',
borderWidth: '1',
dataLabels: {
enabled: true,
color: 'white',
formatter: function() {
if (this.percentage < 10)
{
return ""
}
else
{
return Math.round(this.percentage,1) + "%";
}
},
style: {
fontSize: '18px'
}
}
}
},
series: [{
data: [30]
},{
data: [10]
}]
});
});
EDIT:
Looks like it's not related to the bar chart being "stackable". It might just be related to the fact that the chart goes to the max 'y' value axis... as seen here in another example: http://jsfiddle.net/zKgsF/1/
As suggested by Cubbuk, you can tweak it with by adding the max value of yAxis.
In addition, you can specify a endOnTick property too.
max: 100.1,
endOnTick: false
For API navigate here and for here is an example.