I'm trying to use Highchart's tickPositioner method to load tick positions via ajax so I can use some already existing logic to do the calculations. It does not seem to be waiting for the tickPositioner method to actually return data though. Anyone know what I'm doing wrong?
My actual code:
tickPositioner: function(min, max) {
$.getJSON('/fred2/graph/ajax-requests.php?action=gtp', {min: min, max: max}, function(data) {
console.log(data.tick_positions);
return data.tick_positions;
});
}
A JSFiddle example: http://jsfiddle.net/TWTZh/
Related
I have a Highchart Stock chart that shows EMA's using Stock chart indicator.
I do not want to use the rangefinder, as the chart should always show 100 candlesticks.
The EMA's work, but need to have extra candlesticks so that the first ones have EMA's. The API returns 100 candlesticks, but the first candlesticks do not have EMA's.
So, what is a good way to either:
Hide the first 50 candlesticks or
Only show the last 100 candlesticks?
I gather this might be done with the range selector, but not sure how to do it programatically.
You need to use setExtremes method. You can call it for example in load event:
chart: {
events: {
load: function() {
const points = this.series[0].points;
const min = points[points.length - 101].x;
this.xAxis[0].setExtremes(min, null, true, false);
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/62djn43u/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
I have two charts here where I was using static data for the candles. Let's consider the second Y-axis, where the max value for the few given candles is 215.
In the code I provided, the max value for this y Axes are set as:
yAxis: [{
...
}, {
max: 215*4
}],
From where we can see that I am hardcoding the value for the max as 215*4. What I need to do is, to be able to dynamically get the current value and to multiply it by 4.
I tried it like:
yAxis: [{
...
}, {
max: this.getExtremes().dataMax * 4
}],
But seems is not working and seems that this.getExtremes() can be used in the events only. So is there any way how can I accomplish to set up max value depending on the current displayed max value?
I also tried the following (but it still does not work).
render: function() {
let yAxisExtremesVolumeMax = this.yAxis[1].getExtremes().dataMax;
this.yAxis[1].update({
max: yAxisExtremesVolumeMax * 4
});
},
Anyway, I am not sure that I want to check it this way, since the render event can be called too many times, so I prefer other alternatives.
Try to use this solution with the load instead the render. Doing update in the render callback creates the infinity loop. Code:
chart: {
events: {
load() {
let chart = this,
max = chart.series[1].dataMax;
chart.yAxis[1].update({
max: max * 4
})
}
}
},
Demo: https://jsfiddle.net/BlackLabel/c6qjnf5z/
Try to use this solution...
load: function () {
let { min, max } = this.yAxis[1].getExtremes();
max = max * 4;
this.yAxis[1].setExtremes(min, max);
}
I have more than one chart in one page, all of them uses same data but in different chart types.
I would like to change all of their time with only one navigator on the top. like using it as a datepicker input, how can i achieve that?
Use afterSetExtremes event callback function and apply the same extremes on the rest charts:
xAxis: {
events: {
afterSetExtremes: function(e) {
var min = e.userMin,
max = e.userMax;
chart1.xAxis[0].setExtremes(min, max, true, false);
chart2.xAxis[0].setExtremes(min, max, true, false);
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/8gc9qwsp/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
https://api.highcharts.com/highstock/xAxis.events.afterSetExtremes
I have seen similar questions just like these (even with similar title) but none of them provide the answer I need.
I have a bar-negative-stack chart with drilldown.
In order to keep the Y-axis centered, I am calculating the maximum value among the series and setting it as the extremes of the chart.
The thing is I haven't find a good place to put this logic. I have tried putting it on redraw or render events but, since I am changing the yAxis, this causes a stackoverflow.
What I have so far that is more or less working is having the drilldown event set up with a setTimeout to delay the calculation, otherwise it would get the values before the drilldown. I would need some event like drilldownFinish.
Here's a working fiddle with this drilldown logic (not on negative-bar-stack though): http://jsfiddle.net/6qpq78do/
Any ideas on how to do this without a setTimeout?
Thanks
Maximum callstack exceeded message is caused by setExtremes function. Its third argument is redraw - it's true by default: https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
So setExtremes will call the redraw event again and the redraw event will call setExtremes and so on...
The solution here is to create a flag (redrawEnbaled) that is going to control the access to the logic placed in redrawEvent and prevent this infinite recursive loop:
var redrawEnabled = true;
(...)
events: {
redraw: function() {
if (redrawEnabled) {
redrawEnabled = false;
let values = [];
this.series.forEach(s => {
s.yData.forEach(v => values.push(Math.abs(v)));
});
let max = values.reduce((acc, val) => (acc > val) ? acc : val, 0);
this.yAxis[0].setExtremes(-max, max);
redrawEnabled = true;
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/zjuy21k5/
I want to add a reference series to my charts (i.e. a reference price). Axis.addPlotLine() does it, but I want to be able to toggle this series from the legend; a plain plotLine does not show up in the graph's legend.
Another reason why plotLine does not seem like a good solution is that it does not get accounted for by the viewport calculations. Which means that toggling other series might lead to the plotLine appearing outside the viewport due to zooming.
The simplest way to accomplish what I want would be, to add a dynamic series via chart.addSeries. But it's impossible to call this method from within a triggered addSeries event because chart.addSeries is set to null while in the event handler.
Tying in to the redraw event creates a whole lot of difficulties as well, because render() can't be called anymore.
How would you go about it?
Update:
As per the comment of Pawel Fus, I unsuccessfully tried the following:
[…]
events: {
load: function (event) {
foo = this;
},
addSeries: function(event) {
console.log(foo) // returns chart object as expected
console.log(foo.addSeries) // undefined
}
}
Solution is to store addSeries on load event, and use stored function when adding series. Live example: http://jsfiddle.net/3bQne/808/
events: {
load: function (event) {
foo = this.addSeries;
},
addSeries: function (event) {
if (iterator) {
iterator--;
foo.call(this, {
data: [100, 200, 100, 100, 200, 300]
});
}
}
},
Still you can stick with plotLine only.
If the position of the line is static that is the best way.
If the position is dynamic then you can still go with plotLine.
There are events for adding and removing plotLine on the fly.
API link
removePLotLine() : http://api.highcharts.com/highcharts#Axis.removePlotLine
addPlotLine() : http://api.highcharts.com/highcharts#Axis.addPlotLine
I hope this will help you.