I am using Highcharts (Highstock) to render a chart on my page.
I am specifying a max and min value for my axis, but despite this I end up with blank space above my graph:
This is what my options look like currently:
var myChart = new Highcharts.Chart('container', {
rangeSelector:{
enabled: false
},
credits: {
enabled: false
},
legend: {
enabled: true,
},
yAxis: [{
opposite: false,
title: {
text: 'Gravity'
},
min: 1,
max: items.options.gravity_max + 0.01
},
{
opposite: true,
title: {
text: 'Temperature (C)'
},
min: items.options.temperature_min - 1,
max: items.options.temperature_max + 1
}],
navigator: {
enabled: false,
},
scrollbar: {
enabled: false
},
series: [{
name: 'Temperature',
data: items.temperature,
dataGrouping: {
enabled: true
},
yAxis: 1,
}, {
name: 'Gravity',
data: items.specific_gravity,
dataGrouping: {
enabled: true
}
},
{
name: 'OG',
data: items.original_gravity,
dataGrouping: {
enabled: true
},
dashStyle: 'dot',
color: '#000'
},
{
name: 'FG',
data: items.final_gravity,
dataGrouping: {
enabled: true
},
dashStyle: 'dot',
color: '#000'
}]
});
Here is a link to a fiddle with a simplified version of the data; http://jsfiddle.net/3eLrn61w/
What is causing that blank space above, and how do I get rid of it?
This is because Highcharts by default will try to start and end an axis on a label. Your current max is 1.071+0.01 (1.081). This is more than the label checkpoint of 1.075, which causes another label to be made.
You can fix this by doing (JSFiddle example):
yAxis: [{
// ...
endOnTick: false
}]
A few other options you might want to evaluate is the matching axis.startOnTick: false, possibly axis.maxPadding: 0 to avoid creating labels that are marginally needed and chart.alignTicks: false to free up the connection between the axis.
An alternative approach will also be to alter the tick positions (axis.tickPositions or axis.tickPositioner) so that they line up better with your min and max values.
Or your third option is to alter your handcoded maximum of the axis (max: items.options.gravity_max + 0.01), so that it does not create such a label gap, f.x. by being max: 1.074.
However, I think your best bet may be with the startOnTick and endOnTick options.
Related
I am trying to create a chart like this one:
:
I have already achieved all of the features except the multi colored line of the area chart. I want to show the different gradients of the chart in different colors, thus I need multiple colors on the line.
I have already tested zones like shown here and also common plugins like this. Both do not work. The zones are applied to the area which I do not want and the plugin can only color lines OR areas but not only lines in area charts.
My current Highcharts settings look like this:
{
title: {
text: null
},
xAxis: {
crosshair: true,
labels: {
format: '{value} km'
},
title: {
text: null
},
opposite: true,
startOnTick: true,
endOnTick: false,
min: 0
},
yAxis: {
startOnTick: true,
showFirstLabel: false,
endOnTick: false,
maxPadding: 0.35,
title: {
text: null
},
min: 100,
labels: {
format: '{value} m'
}
},
plotOptions: {
dataGrouping: {
enabled: false
},
showInNavigator: true,
stacking: 'normal',
series: {
dragDrop: {
draggableY: true
},
point: {
events: {
mouseOver: (e) => {
this.chartHover.emit({
distance: e.target.x * 1000
});
},
}
},
},
area: {
dragDrop: {
draggableY: true,
dragPrecisionY: 1
}
}
},
credits: {
enabled: false
},
legend: {
enabled: false
},
chart: {
update: true,
styledMode: true,
marginBottom: 0,
marginRight: 0
},
tooltip: {
headerFormat: '',
pointFormatter: function () {
let point = this;
if (!this.series) {
return;
}
return '<span class="tooltip-area-series-' + this.series.index + '">\u25CF</span> ' + point.series.name + ': <b>' + point.y + 'm</b><br/>';
},
shared: true
},
series: [],
};
Is there an built-in solution for this?
EDIT:
I used the proposed solution by ppotaczek:
series: [{
type: 'areaspline',
id: 'areaSeries',
data: data
}, {
type: 'spline',
linkedTo: 'areaSeries',
data: data,
zoneAxis: 'x',
zones: [{
color: 'red',
value: 2
}, {
color: 'green',
value: 4
}]
}]
This works pretty good, but has some performance pitfalls when you try to add approx. more than 150 zones on desktop browsers.
There is also a small rendering issue - small gaps between the zones.
Best,
Philipp
You can add an extra spline series with zones:
series: [{
type: 'areaspline',
id: 'areaSeries',
data: data
}, {
type: 'spline',
linkedTo: 'areaSeries',
data: data,
zoneAxis: 'x',
zones: [{
color: 'red',
value: 2
}, {
color: 'green',
value: 4
}]
}]
Live demo: http://jsfiddle.net/BlackLabel/8er6y4u3/
API: https://api.highcharts.com/highcharts/series.spline.zones
My current chart
Just started using HighCharts. I'm charting a stock price that fluctautes around $1,598 and $1,601 that fluctuates over the course of a day. The changes are all obviously small - but the price is changing - it should not be a straight line. HighCharts seems to just zoom too far out. I've added the startOnTick: false etc. with no luck so far. Is there anything obvious I might be missing?
Options below:
const options = {
chart: {
height: '150px',
backgroundColor: theme.colors.white02
margin: 0,
spacing: [0, 0, 0, 0]
},
xAxis: {
title: {
text: null
},
labels: {
enabled: false
},
startOnTick: false,
endOnTick: false,
type: 'datetime',
gridLineWidth: 1,
},
yAxis: {
title: {
text: null
},
labels: {
enabled: false
},
startOnTick: false,
minPadding: 10,
maxPadding: 0
},
title: {
text: null
},
legend: {
enabled: false
},
series: [
{
type: 'areaspline',
data: data[0].data,
}
]
};
If you set the min option for the y-Axis to a number just below your minimum - in your case perhaps 1595, and have startOnTick to false as you've mentioned, that will essentially 'zoom in' on the graph right away for your desired range given the inputs are within that range.
Try to set min value of yAxis.
const options = {
chart: {
height: '150px',
backgroundColor: theme.colors.white02
margin: 0,
spacing: [0, 0, 0, 0]
},
xAxis: {
title: {
text: null
},
labels: {
enabled: false
},
startOnTick: false,
endOnTick: false,
type: 'datetime',
gridLineWidth: 1,
},
yAxis: {
title: {
text: null
},
labels: {
enabled: false
},
startOnTick: false,
minPadding: 10,
maxPadding: 0,
min: 1550
},
title: {
text: null
},
legend: {
enabled: false
},
series: [
{
type: 'areaspline',
data: data[0].data,
}
]
};
options.yAxis.min=1550;
or you can assign minimal value from response array.
I would like to set my line graph to have a minimum of 0 and maximum of 100 and even when its a combined line graph the value of the line graph maximum should always remain at 100 even though the other graph y axis increase
So i have
title: {
text: 'Mombasa Plant Truck Compliance reports'
},
credits: {
enabled: false
},
chart: {
zoomType: 'xy'
},
subtitle: {
text: ''
},
xAxis: {
categories: xaxis,
crosshair: true
},
yAxis: [{ // Primary yAxis
title: {
text: 'Passed Inspection',
},
},
{ // Primary yAxis
title: {
text: 'Failed Inpsection',
},
},
{ // Tertiary yAxis
gridLineWidth: 0,
title: {
text: 'Percentage Compliance',
},
labels: {
format: '{value} %',
},
max: 100,
min: 0,
opposite: true
}
],
plotOptions: {
column: {
dataLabels: {
enabled: true,
crop: false,
overflow: 'none'
}
}
},
tooltip: {
shared: true
},
series: chartdata
}
So the above generates
As you can see the line graph y axis appear to be increasing beyond 100%.
I would like it to be at a maximum of 100
What do i need to adjust as i have already set max: 100, min: 0, but it doesnt work.
If you don't want to relay only on Highcharts algorithms for finding ticks, you can use tickPositions or tickPositioner:
https://api.highcharts.com/highcharts/yAxis.tickPositions
https://api.highcharts.com/highcharts/yAxis.tickPositioner
Demo for tick positions: http://jsfiddle.net/BlackLabel/cuutqgys/
Another approach that will work in this particular case is setting endOnTick to false: http://jsfiddle.net/BlackLabel/dxq4y822/
I need to display the average of the values of my 2 datasets, but with a specific characteristic: when the users zoom the chart, the average line is recalculated ONLY with the values of the zoomed area.
How is this done?
Here is my JS:
$(function () {
$('#container').highcharts({
chart: {
type: 'scatter',
zoomType: 'xy'
},
title: {
text: 'Test'
},
subtitle: {
text: ''
},
xAxis: {
type: 'datetime',
title: {
enabled: true,
text: 'Date'
},
startOnTick: true,
endOnTick: true,
showLastLabel: true
},
yAxis: {
title: {
text: ''
}
},
legend: {
layout: 'vertical',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 70,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF',
borderWidth: 1
},
plotOptions: {
scatter: {
marker: {
radius: 5,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
states: {
hover: {
marker: {
enabled: false
}
}
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.x} date, {point.y} dose'
}
}
},
series: [{
name: 'ag',
color: 'rgba(223, 83, 83, .5)',
data: [[1426719600000,0.9659],[1426719600000,0.8928],[1445205600000,1.6428],[1445205600000,1.4711],[1445205600000,1.4209],[1445205600000,1.9574],[1445205600000,1.1226],[1445205600000,0.8159],[1445205600000,1.0114],[1445205600000,0.9168],[1445464800000,1.175],[1445464800000,1.2219],[1445464800000,1.2641],[1445464800000,1.3006],[1445464800000,0.9375],[1445464800000,0.8966],[1445464800000,0.9374],[1445464800000,1.0811]]
}, {
name: 'cf',
color: 'rgba(119, 152, 191, .5)',
data: [[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.015],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.265],[1445378400000,2.015],[1445378400000,2.015],[1445378400000,2.015],[1445464800000,1.2254],[1445464800000,1.1065],[1445464800000,1.3482],[1445464800000,1.3015],[1445292000000,1.2297]]
}]
});
});
Thanks in advance!
This can be done several ways. I am going to show you the way to do it via chart.events.redraw. Whenever you do a zoom (or reset zoom) the chart is redrawn and this gives us a good hook into calculating and adding items to chart at that time. Here is the code block for the redraw event:
Here is a live demo.
I made it verbose so you can see each step. We are going to use getExtremes() to find out what are max and min xAxis and yAxis indexes are. From this we determine if the points in each series are within this "window". If they are not within the window we ignore. If they are then we add the y-value to a var and increment the point counter by 1. Once we are done we do a simple check to make sure we are not going to divide by zero and then calculate the average.
Once we have the average we then will draw a plotLine at the value of the average we calculated above. First we see if a plotline exists with our id. If it does we remove it. Then we create our new plotline.
There is some clean up to do as well (such as, do you include a 0-value plotline based on your business rules) but this should get you started.
Attempted to add code block in edit as original answer attempt would not let it through. Still unable to post code block.
I am new to highChart and even after following the documentation I am not able to correctly plot the x-axis. It only labels the the first element of the dateAndTimeArray array.Can you please tell me where I am making mistake. Here is my code.
JSON Array
var jsonObj=[ {
name:"Nov-10 18:00",
data:[50],
type:'column'
},
{
name:"Nov-20 20:00",
data:[60],
type:'column'
},
{
name:"Nov-10 22:00",
data:[70],
type:'column'
},
{
name:"Nov-12 20:00",
data:[80],
type:'column'
}]
HighChart related code
dateAndTimeArray = ['Nov-15 18:00', 'Nov-20 20:00', 'Nov-11 22:00', 'Nov-12 20:00'];
var seriesData=jsonObj;
console.log(seriesData);
$('#container').highcharts({
chart: {
zoomType: 'xy',
spacingRight: 10
},
credits: {
enabled: false
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
labels: {
overflow: 'justify'
},
startOnTick: true,
showFirstLabel: true,
endOnTick: true,
showLastLabel: true,
categories: dateAndTimeArray,
tickInterval: 00,
labels: {
formatter: function() {
return this.value.toString().substring(0, 6);
},
rotation: 0.1,
align: 'left',
step: 10,
enabled: true
},
style: {
fontSize: '8px'
}
},
yAxis: {
title: {
text: 'Measurement value'
}
},
tooltip: {
xDateFormat: '%Y-%m-%d %H:%M',
shared: true
},
legend: {
enabled: false
},
plotOptions: {
area: {
fillColor: {
linearGradient: {
x1: 0,
y1: 0,
x2: 0,
y2: 1
},
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
lineWidth: 1,
marker: {
enabled: false
},
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
// threshold: null
}
},
series:jsonObj
});
DEMO
The chart is plotting what you asked it to. You have 4 series of data. Each series has one data point. I think you confusing the series.name and xAxis point. Since each of your series has just one point it is assigned to the first category in your xAxis.categories.
The question then becomes:
Do you want to have a categorical xAxis or a datetime xAxis?
Your data leads itself to categorical but your xAxis.categories don't line up with your series.name entries and your xAxis.categories are not in ascending time order. You also are setting a categorical list of items but telling highcharts that your chart is type: 'datetime'. You need to pick one.
Here is an example using categorical type.
Here is an example using datetime type.