I want to display last chart point in the center of the Y axis always. To do this I use setExtremes() function. With integer values this solution works fine. But then it comes to float values it doesn't.
https://jsfiddle.net/antongrinenko/jj33wd2p/1/
$(function () {
$('#chart').highcharts('StockChart', {
chart: {
type: 'line'
},
series: [{
name: 'SomeData',
data: [[1, 1.1111], [2, 2.2222], [3,3.3333]]
}],
yAxis: {
floor: 0
}
});
var newValue = 2.82654;
var series = $('#chart').highcharts().series[0];
series.addPoint([4, newValue]);
var extr = series.yAxis.getExtremes();
var delta = Math.max(extr.dataMax - newValue, newValue - extr.dataMin);
series.yAxis.setExtremes(newValue - delta, newValue + delta);
});
How can I fix it?
It is caused by default options yAxis.startOnTick and yAxis.endOnTick (both set to true) - Highcharts are rounding extremes to start/end on a "nice-number" tick. You can disable that by setting those option to false, see: https://jsfiddle.net/jj33wd2p/2/
Related
Is there a way to show plotlines even when the associated axis has visible: false? Is seems that hiding the axis also hides the plotlines.
More details...
I'm drawing a diagram of a day, like this:
I simply want to add a vertical line at certain times, line the "Now" time, etc.
If I do that using a plot line, then the axis shows up too:
I definitely do not want the axis to show.
My plan now is to draw my own line on the chart using render.rect or render.path. Is there another option?
I found a relatively trivial solution... just hide it with css:
.highcharts-xaxis {
display: none;
}
and in js:
xAxis: {
type: 'datetime',
labels:{
enabled: false
}
}
You can extend Highcharts by wrapping the method responsible for redrawing an axis.
Highcharts.wrap(Highcharts.Axis.prototype, 'redraw', function(p) {
p.call(this);
console.log(this);
var axis = this,
each = Highcharts.each,
options = this.options;
// move plot lines and bands
if (!axis._addedPlotLB) { // only first time
each((options.plotLines || []), function(plotLineOptions) {
axis.addPlotBandOrLine(plotLineOptions);
});
axis._addedPlotLB = true;
}
each(this.plotLinesAndBands, function(plotLine) {
plotLine.render();
});
});
example: http://jsfiddle.net/ncs81btt/
The solution above is not very elegant, though. Much better ways to do it is using Renderer or hide particular axis elements (labels, ticks, etc.).
Depending on what you need from plot lines functionality, using renderer requires to do some calculations.
var customPlotLines = [{
value: 5,
color: 'red',
width: 3
}, {
value: 10,
color: 'yellow',
width: 3
}]
function renderPlotLines() {
var axis = this.xAxis[0],
top = axis.chart.plotTop,
bottom = top + axis.chart.plotHeight,
path = [
'M', null, top,
'L', null, bottom
];
if (!this.customPlotLines) {
this.customPlotLines = customPlotLines.map(plotLine => {
return this.renderer.path([]).add();
});
}
this.customPlotLines.forEach((plotLine, i) => {
var opt = customPlotLines[i];
path[4] = path[1] = axis.toPixels(opt.value);
plotLine.attr({
d: path.join(' '),
'stroke-width': opt.width,
stroke: opt.color
});
});
}
Hook into load/redraw event, so the elements will resize.
chart: {
zoomType: 'xy',
events: {
load: renderPlotLines,
redraw: renderPlotLines
}
},
example: http://jsfiddle.net/ncs81btt/1/
I have a HighStock charge with a scrollbar very similar to this one
http://jsfiddle.net/gh/get/jquery/3.1.1/highslide-software/highcharts.com/tree/master/samples/stock/demo/navigator-disabled/
Highcharts.stockChart('container', {
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Stock Price'
},
navigator: {
enabled: false
},
series: [{
name: 'AAPL Stock Price',
data: data,
tooltip: {
valueDecimals: 2
}
}]
});
I want the default scroll position to be somewhere in the middle of the chart though, is there any way to do this?
You can do this with xAxis.setExtremes on the chart.events.load call. A simple example (using arbitrary 1 year range):
chart: {
events: {
load: function() {
this.xAxis[0].setExtremes(
Date.UTC(2013, 0, 1),
Date.UTC(2013, 11, 31)
);
}
}
},
Example jsFiddle.
If you need to determine what your "middle" is it can depend on your data source where you could pre-calculate it or you could do it also on the chart.events.load call.
For fun I added the mid-point calculations. This uses moment.js because it is much easier than rolling your own time methods.
minX = data[0][0];
maxX = data[data.length - 1][0];
midX = minX + ((maxX - minX) / 2);
var midDate = new Date(midX);
var startDate = moment(midDate);
var endDateMoment = moment(midDate);
startDate.subtract(1.5, 'months');
endDateMoment.add(1.5, 'months');
Note that I am addinng/subtracting 1.5 months to make your 3 month range selector valid. The moment.js library rounds those up to 2 months. You get the idea though. So your setExtremes becomes:
this.xAxis[0].setExtremes(
startDate.valueOf(), //.valueOf() in this context converts to javascript time
endDateMoment.valueOf()
);
And here is live jsFiddle.
I created a polar graph. It has some complicated title-lables. It looks as expected on desktop:
But when it's on mobile, the title-lables don't have enough room to show up. And HighCharts neither did it for me. So it looks like this:
What I desire is to move the two title-labels under the triangle, without changing how it behaves in Desktop view.
What can I do to achieve this?
Thanks!
You can translate labels using tick.label.attr({ x: new_x }); method. For example, create some reposition method:
function reposition () {
var chart = this,
xAxis = chart.xAxis[0],
tick, bbox, xy;
$.each(xAxis.tickPositions, function(i, pos){
tick = xAxis.ticks[pos];
if (tick && tick.label) {
bbox = tick.label.getBBox(); // get label's bounding box
xy = tick.label.xy; // get label's xy position
if (xy.x - bbox.width < 0) {
tick.label.attr({
x: bbox.width
});
}
if (xy.x + bbox.width > chart.plotWidth + chart.plotLeft) {
tick.label.attr({
x: chart.plotWidth + chart.plotLeft - bbox.width
});
}
}
});
}
Which will be called on each chart redraw and starting load events:
$('#container').highcharts({
chart: {
polar: true,
type: 'line',
events: {
redraw: reposition,
load: reposition
}
},
...
});
Live demo: http://jsfiddle.net/wmgbbp9k/
I'm drawing a really simple line chart with hours slept each day. So hours are on the y axis and dates on the x axis. The y axis goes from 0 to 23, but interesting values are usually between 3 and 12, so I only want to draw these values. This is easy, just define min and max on yaxis.
But now highcharts will still draw values above and below the min and max y valus. What I want is to have it just draw values above 12 on the 12 max grid line, and show the real value in the tooltip, and the inverse for values below 3.
Illustration of problem: https://jsfiddle.net/HhP39/10/
$(function () {
$('#container').highcharts({
chart: {},
yAxis: {
title: {
text: 'Hours'
},
min: 3,
max: 12,
tickInterval: 1
},
series: [{
data: [2,6,13,4,9,12,6,8,1,15,9,7,5,8,14,5,8,2,3]
}]
});
});
As you can see, values just out of range, such as 2, will still produce a tooltip if you hover over where they are. I want all values like these to move to be on the min and max lines.
Anybody got any ideas?
Take a look at this update to your fiddle: https://jsfiddle.net/HhP39/7/
It's creating an array of the original values and then an array of the adjusted values. The graph actually charts the adjusted values but the tooltip pulls from the original values.
data = [2,6,13,4,9,12,6,8,1,15,9,7,5,8,14,5,8,2,3];
series = [];
tooltips = [];
for (var i in data) {
tooltips.push(data[i]);
series.push( Math.max(3, Math.min(data[i], 12)) );
}
And then chart it with:
$('#container').highcharts({
chart: {},
yAxis: {
title: {
text: 'Hours'
},
min: 3,
max: 12,
tickInterval: 1
},
tooltip: {
formatter: function() {
return ('Real value: ' + data[this.x]);
}
},
series: [{
data: series
}]
});
I'm pretty clueless at this point, on some of my charts I am giving these options:
var plotOptions, yAxis;
plotOptions = {
series: {
compare: 'value'
}
};
yAxis = {
labels: {
formatter: function() {
return this.value;
}
},
plotLines: [
{
value: 0,
width: 2,
color: 'silver'
}
]
};
And the chart still displays percentages in the y-axis, just without the % sign. I did a console.log of 'this' in the formatter tag, and the value attribute is correct (that is, returning the value instead of a percentage, but it doesn't seem to be applying it to the chart. Any thoughts?
I actually just ended up using a spline chart instead. Basically what I was trying to say was that the y-axis was displaying the same values where I used "compare: 'percentage'" or "compare: 'value'", but the spline chart seems to be rendering the labels as the actual data points (4000 as opposed to 25%).