I am showing two lines in a single graph updating them each second with a value that is saved into a global variable (both have different global variables). An example of the code can be found here: jsFiddle example.
As you can see the two lines are on top of each other, even though they have different values when the ymin and ymax are added to the lines (you can see this in the console).
The cause appears to be in the first addPoint call (line 118). If the first boolean is set to true (like the second addPoint call) the lines are shown correctly but the animation is wrong: jsFiddle example.
Does anyone know why the lines are on top of each other while their values are obviously different? And more importantly: how can I fix this while keeping the smooth animation?
Previous (possibly related) question: Chart not moving fluently when adding value to two lines on interval.
The problem is with using the same variable emptyarray for both series. This is known issue with Highcharts (roported on github) that Highcharts overwrites some of options passed to the chart. Possible solution is to use function which will return that empty array, for example:
function generateArray(){
var emptyarray = [],
time = (new Date()).getTime(),
i;
for (i = -50; i <= 0; i++) {
emptyarray.push({
x: time + i * 1000,
y: 230
});
}
return emptyarray;
}
chartinfo.series = [{
name: 'Minimum Voltage',
data: generateArray(),
color: '#FFFFDD'
}, {
name: 'Maximum Voltage',
data: generateArray(),
color: '#B72E8D'
}];
Working jsFiddle: http://jsfiddle.net/XAHa4/2/
It looks like strange with your setInerval functions, because minified example http://jsfiddle.net/DxqUj/ works properly.
Related
I found a lot of answers for this question, but no one fit mine.
So, we can see that regular tooltip is located above the point, like in this picture:
And when I change this example to use shared:true, the tooltip located in the left side:
Now I just want that shared tooltip will be located above the 2 points(in the example).
I know that I need to add code in the property positioner, but I cant figure out the math. more than that, if outside: true than I absolutely can't understand the math.
So, to conclude, how to make the position in shared tooltip to be above the points?
Thanks in advance.
Ok, it's really annoying task!
So I give a solution for shared tooltip and outside: true.
So first problem was to understand the coordinates system.
When outside: true we work relative to window, and when outside: false we work relative to chart.
Second, you can see if you put a log, that point values are always relative to chart, so what to do when we do outside: true?
Here the code which worked for me:
outside: true,
positioner: function(labelWidth, labelHeight, point) {
const chart = this.chart;
const chartPosition = chart.pointer.getChartPosition();
const hoverPoints = chart.hoverPoints;
const highestPoint = [...hoverPoints].sort((a, b) => a.plotY - b.plotY)[0];
const middlePoint = hoverPoints[Math.floor(hoverPoints.length / 2)];
return {
x:
chartPosition.left +
middlePoint.barX +
chart.plotLeft +
middlePoint.pointWidth / 2 -
labelWidth / 2,
y: chartPosition.top + highestPoint.plotY - labelHeight
};
},
I used a little the solutions from:
How to position highcharts tooltip above chart with outside:true
Highcharts custom tooltip positioner
To a little bit explain my solution, i share a picture:
Till now I'm not 100% understand what exactly each property say, but it's the way.
To investigate further, I suggest you to put a lot of console.logs on the properties, and also I used this code pasted to Console in devtools:
addEventListener('click', (event) => {
console.log(`x: ${event.clientX}, y: ${event.clientY}`);
})
It helped me to create a target, for example:
"The middle need to be in x:250 and y:300 because I clicked on the middle and got this values => let's play with the properties to get closer as I can!"
I have two charts that are synchronized. They have a margin left to make sure they are uniformly aligned. I have situations where I have multiple yAxis that can get turned on and they are on the right side opposed to the left. I attempted to use the same marginRight approach but when a second, third, or fourth axis gets added to the right it won't show up because there isn't enough room. So I am dealing with a dynamic amount of space over there on the right side. Highcharts handles the dynamic aspects when it's just one chart but I need my second chart to have the same margin even tho it doesn't have these additional yAxis. It's important that this time series data remains aligned in the two charts.
What is the approach to handle this?
UPDATE:
I created a simple jsFiddle here: http://jsfiddle.net/28hrffv7/
In my real-world example, I have showEmpty set to false and a series which is hidden by default.
{ opposite: true, title: { text: 'Random Text' }, showEmpty: false}
When they turn it own the series is rendered and the axis and title is added. This example shows that the first charts doesn't realize that the 3rd chart has 3 axis and as a result should have more marginleft
Update 2: Updated JS fiddle to show the more dynamic nature of the problem. When you toggle a series in the legend you can observe axes getting added and removed which is feature that is wanted. What is required is to keep all the charts synchronized in the width of the plotable area so they all line up correctly. http://jsfiddle.net/28hrffv7/3/
You could hard-code marginRight as well as marginLeft.
Demo #1: http://jsfiddle.net/28hrffv7/1/
Or check which marginRight is the highest and update all chart with the new setting. Relevant part of the code:
}, {
data: []
}]
}, function(chart){
if (chart.marginRight > topMarginRight) {
topMarginRight = chart.marginRight;
console.log(topMarginRight);
}
});
}); // end of the each function creating the charts
$.each(Highcharts.charts, function (i, chart) {
chart.margin[1] = topMarginRight;
chart.isDirtyBox = true;
chart.redraw(false);
})
Demo #2: http://jsfiddle.net/28hrffv7/4/ (for Highcharts < 5.0.0)
UPDATE:
With Highcharts 5+ the same is possible through a chart update.
$.each(Highcharts.charts, function (i, chart) {
chart.update({
chart: {
marginRight: topMarginRight
}
});
})
Demo #3: http://jsfiddle.net/28hrffv7/5/
In case of multiple series in each chart you could call a custom function for events like load, redraw, afterAnimate.
Demo #4: http://jsfiddle.net/acjaLxj1/1/
This a sample in highcharts for what exactly i need to create. The issue i am facing is the blue color should be in the area chart series, but highchart is applying the color at the top (outside the series). I apologize if i am not able to explain the issue correctly.
This happens when i use reversed: true, in yAxis.
Please help or let me know if you need me to explain the issue in different words.
When you reverse the axis, the data reverses as well, to match.
I would probably do this by using negative values as the axis min/max, and the data points.
Then, in the axis label formatter, return the absolute value (removing the '-').
labels: {
formatter: function() {
return Math.abs(this.value);
}
}
You can use the same formatting method to fix the tool tips, data labels, and anything else that might need it.
Example:
http://jsfiddle.net/jlbriggs/MybCM/27/
I have a working time history plot that removes one data point as another one is added after two minutes of data has accumulated. The trouble is that after say 10 minutes it is fairly difficult to see the duration of the data set being displayed (even using tickInterval). Is there a way to display fixed x axis labels after two minutes of data has accumulated? Specifically, I'm looking for truly fixed labels that do not scroll to the left with the data.
I tried using setCategories:
chart.xAxis[0].setCategories(cats, true);
Where cats is an array with sacrificial values prepended that will be removed during the shift, but the x axis labels still scroll left and I don't want that.
Thanks.
Edit:
I guess the way I previously described what I wanted to display on the x axis is not ideal. A better way to display this time (x) axis would be to have -120 on the far left and 0 on the far right. This would still require a non-scrolling x axis where the left most data point is over -120 and the right most data point is over 0.
If I'm following you, you want to shift off the start of the series, but leave the xAxis alone?
You can just set an xAxis min:
xAxis:{
min: 0
}
See example.
EDITS
In response to your comment. I think the easiest thing to do would be to shift the data yourself and then use setData to redraw the series.
newData = [];
var seriesData = chart.series[0].data;
// shift the data
for (var i = 0; i < (seriesData.length - 1); i++){
newData.push({x: seriesData[i].x, y: seriesData[i+1].y});
}
// new point for last
newData.push({x: seriesData[seriesData.length - 1].x,
y: Math.random() * 100});
chart.series[0].setData(newData, true);
Updated fiddle.
I am drawing a line chart with monthly data points. However, I want the scale to display year strings only.
So far, so easy. However, as far as I can see, Highcharts will always draw the xAxis labels relative to the ticks... and I am required to display them centered between ticks.
Is there some simple way of doing this that I am missing, please...?
According to my understanding, the behavior you desire is: http://jsfiddle.net/msjaiswal/U45Sr/2/
Let me break down the solution :
1. Monthly Data Points
One data point corresponding to one month :
var data = [
[Date.UTC(2003,1),0.872],
[Date.UTC(2003,2),0.8714],
[Date.UTC(2003,3),0.8638],
[Date.UTC(2003,4),0.8567],
[Date.UTC(2003,5),0.8536],
[Date.UTC(2003,6),0.8564],
..
]
2. Scale to display only yearly ticks
Use chart options like this:
xAxis: {
minRange : 30 * 24 * 3600 * 1000, //
minTickInterval: 12* 30 * 24 * 3600 * 1000 // An year
},
There is no simple, out-of-the-box solution. You have to use events and reposition the labels accordingly. Here is a sample solution that also works when resizing the browser window (or otherwise forcing the chart to redraw), even when the tick count changes: http://jsfiddle.net/McNetic/eyyom2qg/3/
It works by attaching the same event handler to both the load and the redraw events:
$('#container').highcharts({
chart: {
events: {
load: fixLabels,
redraw: fixLabels
}
},
[...]
The handler itself looks like this:
var fixLabels = function() {
var labels = $('div.highcharts-xaxis-labels span', this.container).sort(function(a, b) {
return +parseInt($(a).css('left')) - +parseInt($(b).css('left'));
});
labels.css('margin-left',
(parseInt($(labels.get(1)).css('left')) - parseInt($(labels.get(0)).css('left'))) / 2
);
$(labels.get(this.xAxis[0].tickPositions.length - 1)).remove();
};
Basically, it works like this:
Get all existing labels (when redrawn, this includes newly added ones). 2. Sort by css property 'left' (they are not sorted this way after some redrawing)
Calculate offset between the first two labels (the offset is the same for all labels)
Set half of the offset as margin-left of all labels, effectively shifting them half the offset to the right.
Remove the rightmost label (moved outside of chart, by sometimes partly visible).
This can be done with a workaround by manually adjusting the label positioning via a callback (called on both load and redraw). Please see the fiddle linked to in my comment on this post: Highcharts - how can I center labels on a datetime x-axis?
There are several xAxis options which may help do what you want.
http://api.highcharts.com/highcharts#xAxis.labels
Take a look at 'align' which specifies whether the labels are to the left or right of the tick, and also 'x' which allows you to specify a x-offset for the label from the tick.
Have you tried to use tick placement ? http://api.highcharts.com/highcharts#xAxis.tickmarkPlacement