Highcharts afterAnimate in combination with xAxis max - highcharts

We are developing some charts using Highcharts.
And we are using the series.events.afterAnimate in combination with an xAxis.max value.
But when we have for example points from Januari until September, but with an xAxis.max value until December the afterAnimate function is called when it reached December we guess..
But we would like have a callback when all the valid points are drawn, and not we it reaches its max value...
is this possible?

That happens because the clipPath width is by default equal width of the plot area. To change it you can overwrite Highcharts.Series.animate method and set clipPath width equal width of the particular series.
EDIT:
Also, note that when the width of the clipPath is shorter and the duration of the animation is the same the animation will be much slower. To make it look better the time has to be shortened - it can be calculated depending on series width and updated in chart load event.
Check demo and code posted below:
Code:
(function(H) {
H.Series.prototype.animate = function(init) {
var series = this,
chart = series.chart,
clipRect,
animation = H.animObject(series.options.animation),
sharedClipKey;
// Initialize the animation. Set up the clipping rectangle.
if (init) {
series.setClip(animation);
// Run the animation
} else {
sharedClipKey = this.sharedClipKey;
clipRect = chart[sharedClipKey];
if (clipRect) {
clipRect.animate({
width: series.group.getBBox().width,
x: 0
}, animation);
}
if (chart[sharedClipKey + 'm']) {
chart[sharedClipKey + 'm'].animate({
width: chart.plotSizeX + 99,
x: 0
}, animation);
}
// Delete this function to allow it only once
series.animate = null;
}
}
})(Highcharts);
Highcharts.setOptions({
chart: {
events: {
load: function() {
var chart = this,
series = chart.series[0],
seriesWidth = series.graph.getBBox().width,
duration = (seriesWidth / chart.plotWidth) * series.options.animation.duration;
chart.series[0].update({
animation: {
duration: duration
}
});
}
}
},
plotOptions: {
series: {
animation: {
duration: 2000
}
}
}
});
Highcharts.chart('container', {
title: {
text: 'Chart with half data but with max data'
},
subtitle: {
text: 'A label should appear when all points are drawn'
},
xAxis: {
type: 'datetime',
min: Date.UTC(2019, 0, 1),
max: Date.UTC(2019, 11, 31),
tickInterval: 2592000000, // month
},
plotOptions: {
series: {
events: {
afterAnimate: function() {
this.chart.renderer.label(this.name + ' has appeared', 100, 70)
.attr({
padding: 10,
fill: Highcharts.getOptions().colors[0]
})
.css({
color: 'white'
})
.add();
}
}
}
},
series: [{
data: [{
x: Date.UTC(2019, 0, 1),
y: 29.9
},
{
x: Date.UTC(2019, 1, 1),
y: 139.9
},
{
x: Date.UTC(2019, 2, 1),
y: 59.9
},
{
x: Date.UTC(2019, 3, 1),
y: 19.9
},
]
}]
});
Highcharts.chart('container2', {
title: {
text: 'Chart with full data'
},
subtitle: {
text: 'A label should appear on the plot area after animate'
},
xAxis: {
type: 'datetime',
min: Date.UTC(2019, 0, 1),
max: Date.UTC(2019, 11, 31),
tickInterval: 2592000000, // month
},
plotOptions: {
series: {
events: {
afterAnimate: function() {
this.chart.renderer.label(this.name + ' has appeared', 100, 70)
.attr({
padding: 10,
fill: Highcharts.getOptions().colors[0]
})
.css({
color: 'white'
})
.add();
}
}
}
},
series: [{
data: [{
x: Date.UTC(2019, 0, 1),
y: 29.9
},
{
x: Date.UTC(2019, 1, 1),
y: 139.9
},
{
x: Date.UTC(2019, 2, 1),
y: 59.9
},
{
x: Date.UTC(2019, 3, 1),
y: 19.9
},
{
x: Date.UTC(2019, 4, 1),
y: 29.9
},
{
x: Date.UTC(2019, 5, 1),
y: 139.9
},
{
x: Date.UTC(2019, 6, 1),
y: 59.9
},
{
x: Date.UTC(2019, 7, 1),
y: 19.9
},
{
x: Date.UTC(2019, 8, 1),
y: 29.9
},
{
x: Date.UTC(2019, 9, 1),
y: 139.9
},
{
x: Date.UTC(2019, 10, 1),
y: 59.9
},
{
x: Date.UTC(2019, 11, 1),
y: 19.9
},
]
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px"></div>
<div id="container2" style="height: 400px"></div>
Demo:
https://jsfiddle.net/BlackLabel/gj7eqkv8/
API reference:
https://api.highcharts.com/highcharts/chart.events.load

Related

highcharts waterfall stack only internediate series

New to Highcharts, trying to generate waterfall chart with stacking only on intermediate stack. (image below)
Please help.
enter image description here
You should be able to achieve something like this by adding these stacking columns as an additional series to the waterfall chart. I think that everything is clearly showed in the demo.
Demo: https://jsfiddle.net/BlackLabel/tmyrk21f/
{
type: 'column',
pointPadding: 0,
stacking: 'normal',
data: [
// First stack
{
y: 50000,
x: 0,
color: 'red'
}, {
y: 50000,
x: 0,
color: 'orange'
}, {
y: 20000,
x: 0,
},
// Second stack
{
y: 500000,
x: 3,
color: 'red'
}, {
y: 400000,
x: 3,
color: 'orange'
}, {
y: 20000,
x: 3,
},
// Third stack
{
y: 145000,
x: 6,
color: 'red'
}, {
y: 100000,
x: 6,
color: 'orange'
}, {
y: 100000,
x: 6,
}
]
}
API: https://api.highcharts.com/highcharts/series.column.groupPadding
API: https://api.highcharts.com/highcharts/series.line.stacking

How to place tooltip above point in highcharts x-range?

I have created highcharts x-range chart with multiple series in one category. Tooltips are displaying above the middle of the category. I'd like it to display above each x-range point. How can I do it?
I've tried to override tooltip positioner. But the argument point contains values plotX and plotY like it is placed on the middle of y value and I can't calculate its real position.
this.tooltipPositioner = function(labelWidth, labelHeight, point){
return {
x: point.plotX,
y: point.plotY
};
};
Live Demo: https://jsfiddle.net/levra/mh7uj93r/
You can use tooltip.positioner but instead of the argument point, you can use hovered point object where you will find the correct point plot values. To get hovered point object use plotOptions.series.point.events.mouseOver callback. Check the code and demo posted below:
HTML:
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/xrange.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
JS:
var hoveredPoint;
var chart = Highcharts.chart('container', {
chart: {
type: 'xrange'
},
title: {
text: 'Highcharts X-range'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: ''
},
categories: ['Prototyping', 'Development', 'Testing'],
reversed: true
},
tooltip: {
positioner: function(labelWidth, labelHeight) {
var x = hoveredPoint.shapeArgs.x,
y = hoveredPoint.shapeArgs.y,
width = hoveredPoint.shapeArgs.width,
tooltipOffsetTop = -10;
return {
x: x + chart.plotLeft + width / 2 - labelWidth / 2,
y: y + chart.plotTop - labelHeight + tooltipOffsetTop
}
}
},
plotOptions: {
xrange: {
point: {
events: {
mouseOver: function() {
hoveredPoint = this;
},
mouseOut: function() {
hoveredPoint = null;
}
}
}
}
},
series: [{
name: 'Project 1',
// pointPadding: 0,
groupPadding: 0,
borderColor: 'gray',
pointWidth: 20,
data: [{
x: Date.UTC(2014, 10, 21),
x2: Date.UTC(2014, 11, 2),
y: 0,
partialFill: 0.25
}, {
x: Date.UTC(2014, 11, 2),
x2: Date.UTC(2014, 11, 5),
y: 1
}, {
x: Date.UTC(2014, 11, 8),
x2: Date.UTC(2014, 11, 9),
y: 2
}, {
x: Date.UTC(2014, 11, 9),
x2: Date.UTC(2014, 11, 19),
y: 1
}, {
x: Date.UTC(2014, 11, 10),
x2: Date.UTC(2014, 11, 23),
y: 2
}],
dataLabels: {
enabled: true
}
},
{
name: 'Project 2',
// pointPadding: 0,
// groupPadding: 0,
borderColor: 'gray',
pointWidth: 20,
data: [{
x: Date.UTC(2014, 10, 23),
x2: Date.UTC(2014, 11, 2),
y: 0,
partialFill: 0.25
}],
dataLabels: {
enabled: true
}
}
]
});
Demo:
https://jsfiddle.net/BlackLabel/51gybnew/1/

How to refresh pane background when update date on gauge highcharts?

I have a problem when I update the gauge chart.
I add some life from my chart using this code:
$(function () {
$.getJSON('my.php', function(data) {
$('.container').highcharts({
chart: {
type: 'gauge',
borderWidth: 0,
width: 170,
height: 200,
marginTop: 0,
},
title: {
text: 'title',align: 'center',x: 0,y: 8,floating: true
},
pane: [{
startAngle: -120,
endAngle: 120,
background: [
{
backgroundColor: {linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },stops: [[0, '#FFF'],[1, '#333']]},borderWidth: 0,outerRadius: '109%'
},
{
backgroundColor: {linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },stops: [[0, '#333'],[1, '#FFF']]},borderWidth: 1,outerRadius: '107%'
},
{
backgroundColor: mybackgroundColor(data,100,120),
},
{
backgroundColor: '#DDD',borderWidth: 0,outerRadius: '105%',innerRadius: '103%'
}
]
}],
yAxis: {
min: 0,
max: 250,
minorTickWidth: 1,
minorTickLength: 10,
minorTickPosition: 'inside',
minorTickColor: '#666',
tickPixelInterval: 30,
tickWidth: 2,tickLength: 10,
tickColor: '#666',
labels: {
step: 2,
rotation: 'auto'
},
title: {
text:'km/h',
y : 85
},
plotBands: [
{
from: 0,
to: 100,
color: '#DDDF0D' /*yellow*/
},
{
from: 100,
to: 120,
color: '#55BF3B' /*green*/
},
{
from: 120,
to: 250,
color: '#DDDF0D' /*yellow*/
},
{
from: 30,
to: 35,
color: '#DF5353' /*red*/
}
]
},
series: [
{
name: 'speed',
data: data,
dataLabels: {
enabled: true,
style: {
fontWeight:'bold',
fontSize: '12px'
}
}
}
]
},
// Add some life
function (chart) {
if (!chart.renderer.forExport) {
setInterval(function () {
chart.series[0].color = "#000";
var point = chart.series[0].points[0];
$.getJSON('mydata.php', function(data) {
point.update(data);
});
}, 3000);
};
});
});
});
my function mybackgroundColor(data,100,120) define the pane backgroundColor, it depends the value of data.
When I update point ussing this part of code:
// Add some life
function (chart) {
if (!chart.renderer.forExport) {
setInterval(function () {
chart.series[0].color = "#000";
var point = chart.series[0].points[0];
$.getJSON('mydata.php', function(data) {
point.update(data);
});
}, 3000);
};
});
The wild was updated, but the background didn't.
I try to do this, but it doesn't work:
this.chart.plotBackground.attr({
fill: '#fff'
})
;
Does anybody has an idea?
It's pane background, not a plotBackground. Anyway, in the fact pane background is stored as one of plotBands. So simple you can update it's color:
chart.yAxis[0].plotLinesAndBands[2].svgElem.attr({
fill: 'green'
});
It's [2], because I want to update red plotBand which is third element from background options in a pane.
And some demo: http://jsfiddle.net/Yrygy/190/

Highcharts VU Meter Gauge numeric display disapears

An interesting little "quirk" using the sample of the VU gauge. When I try to reposition the gauge pane, the numeric display will just disappear. If I keep the position <= 100%, the display will show, anything > 100% and the numeric display is gone.
I have repeatedly tried to force the display back into a position where it can be seen, but no luck. Any ideas? Here is the latest test fiddle:
VU Meter Fiddle
Adjusting the elements is easy, use the pane: section to move the entire gauge with the display pane, use the datalabel: section to move the numeric display.
$(function () {
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'gauge',
plotBorderWidth: 1,
plotBackgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0, '#FFF4C6'],
[0.3, '#FFFFFF'],
[1, '#FFF4C6']
]
},
plotBackgroundImage: null,
height: 200
},
title: {
text: 'Efficiencies'
},
/***
in order to move the gauge up or down in the pane, adjust the 'Y' element in
the center array. Adjusting this above 100% (to move the gauge DOWN)
will cause the numeric display to disappear
***/
pane: [{
startAngle: -45,
endAngle: 45,
background: null,
center: ['25%', '100%'],
size: 200
}, {
startAngle: -45,
endAngle: 45,
background: null,
center: ['75%', '105%'],
size: 200
}],
yAxis: [{
min: 0,
max: 110,
minorTickPosition: 'outside',
tickPosition: 'outside',
labels: {
rotation: 'auto',
distance: 20
},
plotBands: [{
from: 0,
to: 70,
color: '#DF5353', // red
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 70,
to: 95,
color: '#DDDF0D', // yellow
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 95,
to: 110,
color: '#55BF3B', // green
innerRadius: '100%',
outerRadius: '105%'
}],
pane: 0,
title: {
text: '<span style="font-size:10px">OEE %</span><br/><span style="font-size:8px">Machine 001</span>',
y: -30
}
}, {
min: 0,
max: 110,
minorTickPosition: 'outside',
tickPosition: 'outside',
labels: {
rotation: 'auto',
distance: 20
},
plotBands: [{
from: 0,
to: 70,
color: '#DF5353', // red
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 70,
to: 95,
color: '#DDDF0D', // yellow
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 95,
to: 110,
color: '#55BF3B', // green
innerRadius: '100%',
outerRadius: '105%'
}],
pane: 1,
title: {
text: '<span style="font-size:10px">Cycle Eff %</span><br/><span style="font-size:8px">Machine 001</span>',
y: -30
}
}],
plotOptions: {
gauge: {
/***
Adjusting the position of the numeric display is also easy
Change the y: component more negative move the display UP,
decreasing the value move the display DOWN
***/
dataLabels: {
enabled: true,
x: 0,
y: -120
},
dial: {
radius: '110%'
}
}
},
series: [{
data: [80],
yAxis: 0
}, {
data: [80],
yAxis: 1
}]
},
// Let the music play
function(chart) {
setInterval(function() {
var left = chart.series[0].points[0],
right = chart.series[1].points[0],
leftVal,
//inc = (Math.random() - 0.5) * 30;
inc1 = Math.random() * (30) + 70;
inc2 = Math.random() * (30) + 70;
leftVal = left.y + inc1;
rightVal = right.y + inc2; // / 3;
if (leftVal < 0 || leftVal > 110) {
//leftVal = left.y - inc;
leftVal = 110 - inc1;
}
if (rightVal < 0 || rightVal > 110) {
rightVal = 110 - inc2;
}
left.update(parseInt(leftVal),false);
right.update(parseInt(rightVal), false);//, false);
chart.redraw();
}, 1500);
});
});
If you use the dataLabels.crop = false option it will show up. But based on the API description it will also show up if the data label is outside the plot area as well, which you may not want. The behavior by highcharts is weird though because it looks at whether the series is outside the plot area and not where the datalabel is when hiding the labels, so I agree that it is a bug.
http://api.highcharts.com/highcharts#plotOptions.series.dataLabels.crop

Using the VU Guage: add the numeric value below needle

In the Highcharts samples, I am seeing that the speedometer has a numeric indicator below the needle pivot (http://jsfiddle.net/radi8/kbvC3/497/). I am going to use the VU gauge but would like to add this numeric indicator to this gauge view. Playing with the fiddle (http://jsfiddle.net/radi8/Z2s77/1/), I cannot seem to get this element to display.
Any suggestions?
My VU from jsFiddle
$(function () {
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'gauge',
plotBorderWidth: 1,
plotBackgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0, '#FFF4C6'],
[0.3, '#FFFFFF'],
[1, '#FFF4C6']
]
},
plotBackgroundImage: null,
height: 200
},
title: {
text: 'Efficiencies'
},
pane: [{
startAngle: -45,
endAngle: 45,
background: null,
center: ['25%', '145%'],
size: 300
}, {
startAngle: -45,
endAngle: 45,
background: null,
center: ['75%', '145%'],
size: 300
}],
yAxis: [{
min: 0,
max: 110,
minorTickPosition: 'outside',
tickPosition: 'outside',
labels: {
rotation: 'auto',
distance: 20
},
plotBands: [{
from: 0,
to: 70,
color: '#DF5353', // red
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 70,
to: 95,
color: '#DDDF0D', // yellow
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 95,
to: 110,
color: '#55BF3B', // green
innerRadius: '100%',
outerRadius: '105%'
}],
pane: 0,
title: {
text: 'OEE %<br/><span style="font-size:8px">Machine 001</span>',
y: -40
}
}, {
min: 0,
max: 110,
minorTickPosition: 'outside',
tickPosition: 'outside',
labels: {
rotation: 'auto',
distance: 20
},
plotBands: [{
from: 0,
to: 70,
color: '#DF5353', // red
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 70,
to: 95,
color: '#DDDF0D', // yellow
innerRadius: '100%',
outerRadius: '105%'
}, {
from: 95,
to: 110,
color: '#55BF3B', // green
innerRadius: '100%',
outerRadius: '105%'
}],
pane: 1,
title: {
text: 'Cycle Eff %<br/><span style="font-size:8px">Machine 001</span>',
y: -40
}
}],
plotOptions: {
gauge: {
dataLabels: {
enabled: false
},
dial: {
radius: '100%'
}
}
},
series: [{
data: [80],
yAxis: 0
}, {
data: [80],
yAxis: 1
}]
},
// Let the music play
function(chart) {
setInterval(function() {
var left = chart.series[0].points[0],
right = chart.series[1].points[0],
leftVal,
//inc = (Math.random() - 0.5) * 30;
inc1 = Math.random() * (30) + 70;
inc2 = Math.random() * (30) + 70;
leftVal = left.y + inc1;
rightVal = right.y + inc2; // / 3;
if (leftVal < 0 || leftVal > 110) {
//leftVal = left.y - inc;
leftVal = 110 - inc1;
}
if (rightVal < 0 || rightVal > 110) {
rightVal = 110 - inc2;
}
left.update(leftVal,false);
right.update(rightVal);//, false);
chart.redraw();
}, 1500);
});
});
You have to enable and position dataLabels (now you have dataLabels: {enabled: false}).
See: http://api.highcharts.com/highcharts#plotOptions.gauge.dataLabels

Resources