Highcharts Dynamic tooltip positioning - highcharts

We are doing a proof of concept with Highcharts so I need to replicate a chart from another system. The other system has the charts laid out as shown on the jsfiddle page. I created 4 axis, and positioned each axis X pixels left of the prior one. the problem is the tooltip for axis 1-3 hover over axis 0. Is there a way to figure out what axis I am hovering, or is there another way to do this layout? I tried using the positioner function, could not get anywhere.
positioner: function (boxWidth, boxHeight, point) {
}
JSFiddle example http://jsfiddle.net/oabg7kjw/

It is known bug reported here
Workaround (using positioner): http://jsfiddle.net/oabg7kjw/1/
tooltip: {
positioner: function(w, h, p) {
return {
x: p.plotX + this.chart.hoverSeries.xAxis.left - w/2,
y: p.plotY
}
}
},
Docs:
- http://api.highcharts.com/highcharts#tooltip.positioner

Another option here is to drop the mutli-axis approach and create one with repeating categories. You'd then need to place each bar at the appropriate category.
categories: ['FY 04', 'FY 05', 'FY 06', 'FY 07', 'FY 08', 'FY 09', 'FY 10', 'FY 11', 'FY 12', 'FY 13',
'FY 04', 'FY 05', 'FY 06', 'FY 07', 'FY 08', 'FY 09', 'FY 10', 'FY 11', 'FY 12', 'FY 13',
'FY 04', 'FY 05', 'FY 06', 'FY 07', 'FY 08', 'FY 09', 'FY 10', 'FY 11', 'FY 12', 'FY 13',
'FY 04', 'FY 05', 'FY 06', 'FY 07', 'FY 08', 'FY 09', 'FY 10', 'FY 11', 'FY 12', 'FY 13'],
In your data:
series: [{
...
data: [[0,147], [1,123], [2,139], [3,127], [4,102], [5,116], [6,59], [7,80], [8,72], [9,91]]
}, {
...
data: [[10,154], [11,102], [12,62], [13,77], [14,11], [15,33], [16,227], [17,145], [18,75], [19,101]]
}, {
etc...
Updated fiddle here.

As old as this topic is, there is another workaround I have found to center the tooltip dynamically either vertically or horizontally. 7 years later this might still help someone:
Assuming your container has been inserted in your project like this:
<div #myChart id="myChart" class="graph-container"></div>
Then you can use the width or height of the div itself to center the tooltip:
....
tooltip: {
positioner: function () {
let customXPosition = (document.getElementById('myChart').offsetWidth / 2);
return {
x: customXPosition,
y: 200
};
},
...
The same approach can be used with height (or the y axis) by using .offsetHeight instead

Related

Highcharts - Indicator's data not showing in line chart

I am fetching data from an endpoint
I display the data in a highchart
There are several indicators that can be selected. For each of them another yAxis is added below the main one.
My series data are of this format :
series: [
{
data: [],
id: 'prices',
step: this.hasStep,
name: this.$props.title,
fillColor: 'rgba(127,183,240,0.2)',
},
{
visible: false,
type: 'column',
id: 'volume',
name: 'Volume_hardcoded',
//linkedTo: 'prices',
data: this.volumeSeries,
},
],
I save the data in the following way (don't pay attention in the logic, it works fine):
if (this.selectedTimeSpan.tickInterval === 1) {
for (let i = 0; i < prices.length; i++) {
let xData = null;
this.selectedTimeSpan.getIntradayData
? (xData = Math.floor(new Date(prices[i].time).getTime()))
: (xData = Math.floor(new Date(prices[i].date).getTime()));
priceSeries[i] = {
x: xData,
open: prices[i].first,
high: prices[i].high,
low: prices[i].low,
close: prices[i].last,
y: prices[i].last,
volume: prices[i].tradingVolume,
};
this.volumeSeries[i] = {
x: xData,
y: prices[i].tradingVolume,
};
}
} else {
let j = 0;
for (
let i = 4;
i < prices.length;
i += this.selectedTimeSpan.tickInterval
) {
priceSeries[j] = {
x: Math.floor(new Date(prices[i].date).getTime()),
open: prices[i].first,
high: prices[i].high,
low: prices[i].low,
close: prices[i].last,
y: prices[i].last,
volume: prices[i].tradingVolume,
};
this.volumeSeries[j] = {
x: Math.floor(new Date(prices[i].date).getTime()),
y: prices[i].tradingVolume,
};
j++;
}
}
When I select these indicators (they are based on the volume), I am getting this result.(You can see a blank space below the main chart.) Instead when i swap to OHLC or candlestick my main series (series[0]) it looks works fine and it looks like this. Any idea why is that happening? I haven't touched the tooltip settings at all (in case it was there a problem). I am struggling 2 days now with it can't really figure it out. Any help would be appreciated a lot. If you need more information feel free to comment so I can provide. Thanks in advance. Chris.
Fixed, there's a flag that can be used called usedOhlcData in series object. (series[0] in my case]. We just set it to true.
series:[{
data:[],
useOhlcData:true,
...}
,{
...
}]

How to display tooltip only for last point?

I am using live random data in my chart . Here i want to display current feed value in right side of chart which will travel along with chart's last point.
I am trying to display tootip in last point which series will added dynamically. But i am unable to add tootip to last point alone.
Can anyone help me to achieve this.
Here is jsfiddle and what i am trying is
To show a tooltip you could use toolip.refresh(point).
Example: http://jsfiddle.net/a6pshutt/7/
...
setInterval(function () {
var x = (new Date()).getTime(),
y = Math.random();
len = series.data.length;
series.addPoint([x,y], false, true);
series2.data[0].update([x,y]);
tooltip.refresh(series2.data[0]); // <----------here
}, 1000);
...
To show a dataLabel you could enable it for the scatter point in your scatter series.
Example: http://jsfiddle.net/83kp2d4t/
...
events: {
load: function () {
var tooltip = this.tooltip,
series = this.series[0],
len = series.data.length;
this.addSeries({
id: 'end point',
type: 'scatter',
marker: {
enabled:true,
symbol:'circle',
radius:4,
fillColor:'white',
lineColor: 'black',
lineWidth:2
},
dataLabels:{
enabled: true // <----------here
},
data: [[
series.data[len - 1].x,
series.data[len - 1].y
]]
});
...

get tickpositions highcharts

I have a highcharts scatter plot for which I'm trying to fetch the x and y tickPositions in freemarker template, specifically the first and last one. Such as that I would get something as [-10,-10] (bottom left corner) at the intersection of the x-y axis and [30,40] (top right corner) at the intersection of the opposite sides, where xAxis ticks are [-10,0,10,20,30] and yAxis ticks are [-10,0,10,20,30,40]
I want these points so that I'll be able to plot a diagonal line across the scatter plot from bottom lower corner to top right corner. The line series should look like:
series: [
{
type : 'line',
<#--diagonal line-->
data :[[-10,-10], [30,40]], // to be calculated dynamically
lineWidth: 0.5,
marker : {
enabled : false
}
},
{
color: 'rgb(0,85,152)',
data: [[2,3],[6,7],[8,9]]
}
]
The problem at present is I'm unable to get [-10,-10], [30,40] data points. Is it even possible is what I'm wondering. Any help is much appreciated!
You have the getExtremes() function on an axis.
For example:
var extremes = $('#container').highcharts().yAxis[0].getExtremes();
Here is the doc, and here is a demo fiddle
Is this what you were trying to achieve ?
Edit
After your fiddle example, I understand better your need.
Here is the updated fiddle
var chart = $('#container').highcharts();
var extremeY = chart.yAxis[0].getExtremes();
var extremeX = chart.xAxis[0].getExtremes();
var lineSeries = {
type: 'line',
data: [
[extremeX.min, extremeY.min],
[extremeX.max, extremeY.max]
],
lineWidth: 0.5,
lineColor: 'rgb(0,0,0)',
marker: {
enabled: false
}
};
chart.addSeries(lineSeries);
I created an object with the properties of the line series. And using min and max (not dataMin and dataMax) properties from the object returned by getExtremes() you obtain the desired result.
Edit 2
You could put this code in the load event of the chart. It is a callback called after the chart finished loading. And here you can use this to refer to the chart :
$('#container').highcharts({
chart: {
events: {
load: function() {
var extremeY = this.yAxis[0].getExtremes();
var extremeX = this.xAxis[0].getExtremes();
var lineSeries = {
type: 'line',
data: [
[extremeX.min, extremeY.min],
[extremeX.max, extremeY.max]
],
lineWidth: 0.5,
lineColor: 'rgb(0,0,0)',
marker: {
enabled: false
}
};
this.addSeries(lineSeries);
}
},
//...
});
Here is the new updated fiddle
Since you need only a diagonal path, then you could add it using renderer
Example: http://jsfiddle.net/cr7gq4st/
function diagonal() {
var chart = this,
ren = chart.renderer,
diag = chart.diag,
attrs = {
'stroke-width': 0.5,
stroke: '#000',
zIndex: 1
},
topR = {
x: chart.plotLeft + chart.plotWidth,
y: chart.plotTop
},
bottomL = {
x: chart.plotLeft,
y: chart.plotTop + chart.plotHeight
},
d = 'M ' + bottomL.x + ' ' + bottomL.y + ' L ' + topR.x + ' ' + topR.y;
if( !diag ) { //if doesn't exist, then create
chart.diag = ren.path().attr(attrs).add();
}
chart.diag.attr({d:d});
}

Highcharts: how to get the data points in the zoomed window?

I am new to Highcharts.
I have a line chart. Here is the categories:
["9/7/14", "9/8/14", "9/9/14", "9/10/14", "9/11/14", "9/12/14", "9/13/14", "9/14/14", "9/15/14", "9/16/14", "9/17/14", "9/18/14", "9/19/14", "9/20/14", ...]
Here is the data series:
[1, 4, 0, 2, 1, 1, 1, 5, 3, 1, 0, 0, 6, 8, ... ]
I added zoom to my chart, very similar to this jsfiddle demo: http://jsfiddle.net/348sh/3/
chart: {
renderTo: 'container',
zoomType: 'x'
},
I would like to get the total of only those Y values within the zoomed-in window, not the total of the entire data series. For this, I need to capture what values are included in the x axis in the zoomed window. So I added the following based on my research:
xAxis: {
type: 'line',
events: {
setExtremes: function(event) {
console.log(event.min);
console.log(event.max);
}
}
}
However, the values for event.min or event.max are numbers such as 3.6552511415525117, 7.10730593607306. I have no way to know which x values are included in the zoomed window. How can I find which x values are included? Any way to get the start and end x values ?
Thanks!
I did further research. I notice that I may have answered my question already in my question. It turns out that the numbers I gave in my question are very helpful, not clueless. Math.ceil(min) and Math.floor(max) are just the beginning and ending index of the data points in the data series that are show up in the zoomed window. The another thing to note is to use afterSetExtremes event. This is the moment where chart finalizes the starting and ending points in the X axis. So the complete answer is:
xAxis: {
type: 'line',
events: {
afterSetExtremes: function(event) {
var start = Math.ceil(event.min);
var end = Math.floor(event.max);
}
}
}
I am new to Highcharts and love to get corrected if I am wrong.
Cheers.
This may help you . Try this fiddle : http://jsfiddle.net/7kv9a25r/ .
chart: {
events: {
selection: function (event) {
var text,
label;
if (event.xAxis) {
text = 'min: ' + Highcharts.numberFormat(event.xAxis[0].min, 2) + ', max: ' + Highcharts.numberFormat(event.xAxis[0].max, 2);
} else {
text = 'Selection reset';
}
label = this.renderer.label(text, 100, 120)
.attr({
fill: Highcharts.getOptions().colors[0],
padding: 10,
r: 5,
zIndex: 8
})
.css({
color: '#FFFFFF'
})
.add();
setTimeout(function () {
label.fadeOut();
}, 1000);
}
},
zoomType: 'x'
},

highcharts converting area range to multiple lines on plot

Need a hand deciphering the Highcharts methodology please.
I have input data that is a lot of records with three fields (timestamp, min, max) that I'd like to generate a plot from. Goal is to have two lines, one with max-vs-time and the other with min-vs.time, both on that one plot.
I got an arearange to work (fiddle here) but if I change the plot type to spline, I just get one line graph with min vs. time (i.e., it ignores the last data parameter).
Same thing happens when I mess with the Highcharts arearange example, so I'm guessing that my series is not defined correctly, but I'm not deciphering the right terminology to figure out how to ask the question yet I guess. Any help appreciated....
// data is timestamp,min,max for the day
// - this currently plots only the min for each day
// - intent is two lines, one for min and one for max
var data = [
[1186124400000, 57.2, 75.6],
[1186210800000, 51.8, 74.7],
[1186297200000, 53.8, 74.8],
[1186383600000, 56.7, 72.7],
[1186470000000, 59.0, 76.1]
];
var options = {
chart: {
renderTo: 'container',
type: 'arearange'
},
title: {
text: 'historical temperatures'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'outsideTemp (F)'
}
},
legend: {
enabled: false
},
series: [{
legend: {
enabled: false
},
data: data
}]
};
$(document).ready(function () {
var chart1 = new Highcharts.Chart(options)
});
You need to create two separate series.
So this:
var data = [
[1186124400000, 57.2, 75.6],
[1186210800000, 51.8, 74.7],
[1186297200000, 53.8, 74.8],
[1186383600000, 56.7, 72.7],
[1186470000000, 59.0, 76.1]
];
Will need to be two separate arrays, each with a single y value, and the same x values:
var data1 = [
[1186124400000, 57.2],
[1186210800000, 51.8],
[1186297200000, 53.8],
[1186383600000, 56.7],
[1186470000000, 59.0]
];
var data2 = [
[1186124400000, 75.6],
[1186210800000, 74.7],
[1186297200000, 74.8],
[1186383600000, 72.7],
[1186470000000, 76.1]
];
Updated Fiddle:
http://jsfiddle.net/jlbriggs/5q5HJ/12/
If your x values are at consistent intervals, you can use the pointStart and pointInterval properties and skip specifying the x values
http://api.highcharts.com/highcharts#plotOptions.series.pointStart
http://api.highcharts.com/highcharts#plotOptions.series.pointInterval

Resources