Y-axis markers are multiples of odd numbers - highcharts

I have a small team of developers working for me to graph some medical data. They have come back with no resolution. Hopefully someone here can help.
When charting a series the y-axis multiples are not the default highchart multiples. For example in highcharts when I plot the below code, the y-axis labels are 0,250,500,750,1000,1250.
However, when I view the graph in my application I get the following: 0,95,190,285,380,475,570,665,760,855,950. See image attached.Odd intervals
The only other information I can provide is that the container size is relative, and when I change the size of the window, the index values change. That would suggest to me that they are not hard-coded to be a fixed multiple.
Highcharts.chart('container', {
title: {
text: 'Solar Employment Growth by Sector, 2010-2016'
},
subtitle: {
text: 'Source: thesolarfoundation.com'
},
yAxis: {
title: {
text: 'Number of Employees'
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
plotOptions: {
series: {
pointStart: 2010
}
},
series: [ {
name: 'Other',
data: [0,100,2,4,8,16,32,64,128,256,512,1024]
}]
});

So a solution is below. Basically, it scans the array for a multiple that is greater than the ideal divider count (in this example 10). It then uses that as the desired interval.
function returnInterval(){
var intervalArray =
[.0001,.001,.01,.1,1,2,5,10,20,50,100,250,500,1000,5000,10000]
var min = .0012 //min from series below
var max = .1001 //max from series below
var idealDivider = (max - min)/10 //where 10 is the number of desired markers
for(var i=0; i<intervalArray.length; i++) {
if (intervalArray[i] >= idealDivider) return intervalArray[i];
}
}
Highcharts.chart('container', {
yAxis:{
tickInterval: returnInterval()
},
series: [{
data: [.0012,.0213,.0123,.0532,.042,.009942,.1001]
}]});

Related

Highcharts: when having multiple columns for the same X axis value, how can I get 1 tooltip per column?

I am using highcharts (StockChart) to draw a timeline of events (X axis therefore represents a datetime) and my JS knowledge is extremely basic. Each event (represented as a bar/column) has some data attached which I show in a tooltip. My timeline has multiple types of event (= series) and it can happen that there is 2 or more events of different types that happen at the exact same time. So in other words, 2 points in the plot series share the same X axis value.
My issue is that in these cases I end up with a timeline that has 2 columns but only 1 tooltip containing a merge of the 2 piece of data.
Here is how it looks like right now:
hover any column
1.7xxxx represents the first column value
3.xxx represents the second column value
To be noted as well: the "snap" point is roughly in the middle of the 2 columns (the slim white vertical bar) instead of on the column itself, which is a bit weird on a UX standpoint.
What I want is to have them split so that each column has its own tooltip floating over the column like a regular scenario.
What I want it to look like (rough sketch):
hover left column
hover right column
Here is how I handle the chart:
return function (yaxisTitle, targetId, dataHighStock) {
// Line timeline chart
// create the chart
var config = {
chart: {
renderTo: targetId,
height: 269,
type: 'column'
},
plotOptions: {
column: {
cursor: 'pointer',
pointRange: 1,
pointPlacement: "on",
pointWidth: 10
}
},
xAxis: {
type: 'datetime',
ordinal: false,
dateTimeLabelFormats: {
millisecond: '%Y-%m-%d',
second: '%H:%M:%S',
minute: '%H:%M',
hour: '%H:%M',
day: '%e. %b',
week: '%e. %b',
month: '%b \'%y',
year: '%Y'
},
minPadding: 0.05,
maxPadding: 0.05
},
yAxis: {
offset: 30,
min: 0,
title: {
text: yaxisTitle
},
labels: {
enabled: true
}
},
rangeSelector: {
inputDateFormat: '%Y-%m-%d',
inputBoxStyle: {
left: '270px',
width: '250px'
},
selected: 5
},
tooltip: {
formatter: function () {
var s = '';
var examDate = new Date(this.x);
var month = examDate.getMonth() + 1;
var day = examDate.getDate();
s = examDate.getFullYear() + "-" + (month < 10 ? '0' + month : month) + "-" + (day < 10 ? '0' + day : day) + "<br />";
$.each(this.points, function (i, point) {
s += point.y+"<br>";
});
return s;
},
snap: 1
},
legend: {
y: 20,
x: 80,
enabled: true,
align: 'left',
layout: 'horizontal',
verticalAlign: 'top',
shadow: true
},
series: dataHighStock
};
//add series to navigator
new Highcharts.StockChart(config, function (loadedChart) {
for (var i = 0; i < dataHighStock.length; i++) {
loadedChart.addSeries($.extend({}, dataHighStock[i],
{
enableMouseTracking: false,
type: "spline",
xAxis: loadedChart.xAxis.length - 1,
yAxis: loadedChart.yAxis.length - 1,
color: loadedChart.options.colors[i],
showInLegend: false
}));
}
});
};
"dataHighStock" is just a regular json I pass, which looks something like this:
[ { type: "column", name: "Event Type 1", color: "#08A5E1", data: [ { x: 1431430804000, y: 1.7153846153846155, name: '1' }] }, { type: "column", name: "Event Type 2", color: "#772971", data: [ { x: 1431430804000, y: 3.63636, name: '14915'}] }, ]
I could make the tooltip "kinda" work (= 1 tooltip per column) when I changed the Highcharts creation to be done through Highcharts.chart(...) instead of Highcharts.StockChart(...) and removing the for loop in the navigator + removing the specific data displayed in the tooltip formatter ($.each(this.points, ......){...}). The downside to that is that I lose all the features of a StockChart (time range, navigator, etc.), obviously, but also the tooltip content.
Here is a jfiddle link that reproduces all this: https://jsfiddle.net/eq3mz7y1/20/
Changing the tooltip.split into false is a solution for your issue. Notice that this solution requires some changes in your formatter callback output because the this.points array doesn't exist anymore.
Demo: https://jsfiddle.net/BlackLabel/01sqhdyv/
API: https://api.highcharts.com/highcharts/tooltip.split

Highcharts update chart scroll issue- scroll to initial position

I am having an issue with Highcharts highstock column chart. With xaxis min=0, max=5 [page size] which has 20 categories.
After the initial load when you scroll the xaxis to the end and then click on modify data. On this action I will invoke an api and update the series data. 'The chart displays as No data to display' even if there is one category. I wanted to reset scroll to initial position, which I cannot do for categories. You will need to move scroll manually
Also Since there is only one category and I do not want other categories to display as numbers.
https://jsfiddle.net/shashi3337/zcf8kvgx/7/
I am updating the chart to modify xaxis min and max to set max as 0 [ 1 category] to remove numbers.
https://jsfiddle.net/shashi3337/zcf8kvgx/5/.
Now when you click on Add data which adds back the data. I am resetting min=0 and max=5. Now
I just see only 1 category per page scroll.
Expected Behavior
I expect the scroll bar to be automatically scrolled back after I click modify data button and when I click on add data button I expect to see 6 categories per page scroll on xaxis.
function test(n) {
var data = [];
for (var i = 0; i < n; i++) {
var value = Math.random() * 10;
var x = {
id: i,
name: 'test ' + i,
y: value
}
data.push(x);
}
return data;
}
var chart = Highcharts.chart('container', {
chart: {
type: 'column',
},
plotOptions: {
column: {
stacking: 'normal'
},
},
xAxis: {
type: 'category',
min:0,
max:5
},
scrollbar: {
enabled: true
},
series: [{
name: "A",
data: test(20)
}, {
name: "B",
data: test(20)
},
{
name: "C",
data: test(20)
},
{
name: "D",
data: test(20)
}
]
});
$(document).ready(function(){
$('#modify').click(function(){
if(chart){
while (chart.series.length > 0)
chart.series[0].remove(true);
chart.addSeries({
name: 'new',
data: test(1)
});
}
});
$('#add').click(function(){
if(chart){
while (chart.series.length > 0)
chart.series[0].remove(true);
chart.update({
xAxis: {
min:0,
max:5
}
});
chart.addSeries({
name: 'A',
data: test(20)
});
}
});
});
Found the answer to this.
You need to use xAxis.setExtremes() to modify extremes on the chart. At this moment, extremes set by user (e.g. by scrollbar) have the highest priority and are not cleared when you remove all series.
Example https://jsfiddle.net/BlackLabel/pp2qpxks/
chart.xAxis[0].setExtremes(0, 0);

HighCharts display total of stacked column in labels

I have a stacked group column graph as shown in the fiddle provided below. In the xAxis labels (red blocks), I would like to display the total of the stacked amounts subtracted from the total of the second column. For example, for "Value1" I want to display 42 in the label (100-(43+15)). Right now, I am only able to access x values, which I am returning in the formatter function (this.value). https://jsfiddle.net/er1187/n6sr0znx/
xAxis: [{
offset: -280,
tickWidth: 0,
lineWidth: 0,
categories: ['Value1', 'Value2', 'Value3'],
labels: {
x: 5,
useHTML: true,
style:{
backgroundColor: 'red',
color: 'white'
},
formatter: function () {
return this.value;
}
}
}, {
linkedTo: 0,
categories: ['Value1', 'Value2', 'Value3']
}]
In the axis formatter you dont have access to the processed data yet. However, you can access the options of series and obtain the raw data.
formatter: function () {
const axis = this.axis;
const points = axis.series.map(series =>
series.options.data[axis.categories.indexOf(this.value)]
);
return points[2] - (points[0] + points[1]);
}
example: https://jsfiddle.net/n6sr0znx/2/

HighCharts Column Overlapping

How do I get HighCharts not to overlap columns in this chart? I have tried all sorts of options. What I would like is for highcharts to set the widths evenly depending on the number data elements in the series, the more the narrower.'
I have specified width: 300 to force the columns to overlap just to show what is happening in narrow chart and only add a few data elements.
$(function() {
Highcharts.chart('container', {
chart: {
type: 'column',
width: 300,
zoomType: 'x'
},
legend: {
enabled: false
},
series: [{
data: [
[102.0, 66815.0],
[96.0, 77760.0],
[90.0, 68710.0],
[84.0, 69452.5],
[78.0, 48807.5],
[72.0, 35472.5],
[66.0, 24595.0],
[60.0, 17790.0],
[54.0, 18010.0],
[48.0, 5635.0]
]
}]
});
});
http://jsfiddle.net/a0kjogh1/3/
Data should be sorted before you put it into the chart. You receive the error in the console.
data.sort((a, b) => {
return a[0] > b[0];
});
example: http://jsfiddle.net/a0kjogh1/4/

Highcharts 3 cannot render more than 1000 points in one series

After upgrading for Highcharts 2.1.9 to 3.0.0 we found that it seems impossible to render more than 1000 points in one series.
If you add 1000 points to a series it renders ok.
If you add 1001 points to a series it does not render at all. If you interrogate the series afterwards the "data" array on the series is empty.
You can however render multiple series with 1000 points - so there does not seem to be a limitation in terms of the total number of points per chart.
Here is a jsFiddle which illustrates this: http://jsfiddle.net/YWVHx/47/
$(function () {
var series1Data = [];
for (var i = 0; i < 1000; i++) {
series1Data.push({
x: (new Date()).getTime() + i * 10000,
y: Math.random() * 100
});
}
var series2Data = [];
// If you change this back to 1000 the series gets rendered
for (var i = 0; i < 1001; i++) {
series2Data.push({
x: (new Date()).getTime() + i * 10000,
y: Math.random() * 100 + 100
});
}
$('#container').highcharts({
chart: {
type: 'line'
},
title: {
text: 'Foo'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: null
}
},
tooltip: {
crosshairs: true,
shared: true,
valueSuffix: '°C'
},
legend: {
enabled: true
},
series: [{
name: '1000 Points - I work ;-)',
data: series1Data
}, {
name: '1001 Points - I dont work :-(',
data: series2Data
}]
});
});
Is this a limitation that was imposed on purpose or is it a problem with v3?
You should set bigger turbothreshold: http://api.highcharts.com/highcharts#plotOptions.series.turboThreshold
For the other user's convenience , this is a complementary example that you can copy and paste:
plotOptions:{
series:{
turboThreshold:5000//set it to a larger threshold, it is by default to 1000
}
}
Check http://jsfiddle.net/YWVHx/339/ here for results

Resources