Dynamic chart is not working properly (highcharts)? - javascript

The problem I am encountering is that the black line is doing some funky stuff compared to the blue line. If you scroll in the middle or somewhere else (use bottom scroll tool), you can clearly see that the black line is changing its shape, while the blue line holds its shape, strange. This only happens when you use the scroll tool.
How can I prevent the black line changing its shape? Copy this code and replace it with the JSfiddle to see the problem:
$(function () {
Highcharts.setOptions({
global : {
useUTC : false
}
});
// Create the chart
$('#container').highcharts('StockChart', {
chart : {
events : {
load : function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
}, 1000);
var series1 = this.series[1];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series1.addPoint([x, y], true, true);
}, 1000);
}
}
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 0
},
title : {
text : 'Live random data'
},
exporting: {
enabled: false
},
series : [{
name : 'diagram1',
data : (function () {
// generate an array of random data
var data1 = [], time = (new Date()).getTime(), i;
for (i = -999; i <= 0; i += 1) {
data1.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data1;
}())
},
{
name : 'diagram2',
data : (function () {
// generate an array of random data
var data2 = [], time = (new Date()).getTime(), i;
for (i = -999; i <= 0; i += 1) {
data2.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data2;
}())
}]
});
});
The only thing I have done is to add an extra dynamic line (black one) to the diagram. Here is the original code without the black line. Review original code

The reason of the movement in the black line is the redraw and the animation function of the chart. For some reason the first series(blue line) doesn't show animation after calling addPoint so you don't see the movement. The second parameter in the addPoint function is redraw. Setting it to false for the second series(black line) will stop the movement when updating the points:
series1.addPoint([x, y], false, true);
Here's the DEMO.

Related

Highchart on mobile (Touch to zoom out and zoom in) - LineChart

I'm trying to apply ZoomIn and ZoomOut in a line chart on a mobile device. The goal is to click on a zone of the chart and ZoomIn in the first click and ZoomOut on the second. The sequence will always be this one.
I already live to see the documentation / examples and I can not find anything to solve this situation.
I have already tried using this properties in the chart: property
pinchType : 'y',
zoomType: 'none'
I tried the zoomtype but the behavior is not what I expect. I want to have a click to zoom this specific area of ​​the chart. I do not want to zoom with two fingers.
{
chart: {
pinchType : 'x'
},
legend: {
itemStyle: {
color: '#fff'
}
},
plotOptions: {
series: {
animation: {
duration: 2000
}
}
},
xAxis: {
tickInterval: 1
},
series: [
{
type: 'spline',
color : '#fff'
},
{
dashStyle: 'longdash',
color: '#b3be77'
}
],
}
As simple as clicking to get zoomin and zoomout
Yes, the second challenge can be easily achieved by adding this logic to plotOptions.series.events.click callback function:
chart: {
events: {
load: function() {
this.clickedOnce = false;
},
click: function() {
const chart = this;
if (chart.clickedOnce) {
chart.zoomOut();
chart.clickedOnce = false;
}
}
}
},
plotOptions: {
series: {
events: {
click: function(e) {
const chart = this.chart,
yAxis = chart.yAxis[0],
xAxis = chart.xAxis[0];
let x,
y,
rangeX,
rangeY;
if (!chart.clickedOnce) {
x = xAxis.toValue(e.chartX);
y = yAxis.toValue(e.chartY);
rangeX = xAxis.max - xAxis.min;
rangeY = yAxis.max - yAxis.min;
xAxis.setExtremes(x - rangeX / 10, x + rangeX / 10, false);
yAxis.setExtremes(y - rangeY / 10, y + rangeY / 10, false);
chart.redraw();
chart.clickedOnce = true;
} else {
chart.zoomOut();
chart.clickedOnce = false;
}
}
}
}
}
Demos:
https://jsfiddle.net/BlackLabel/kotgea5n/
https://jsfiddle.net/BlackLabel/s8w2xg3e/1/
This functionality is not implemented in Highcharts by default, but you can easily achieve it by adding your custom logic when the chart area is clicked.
When area is clicked the first time use axis.setExtremes() method to zoom in. On the second click use chart.zoomOut() to zoom out the chart. Check demo and code posted below.
Code:
chart: {
events: {
load: function() {
this.clickedOnce = false;
},
click: function(e) {
const chart = this,
yAxis = chart.yAxis[0],
xAxis = chart.xAxis[0];
let x,
y,
rangeX,
rangeY;
if (!chart.clickedOnce) {
x = xAxis.toValue(e.chartX);
y = yAxis.toValue(e.chartY);
rangeX = xAxis.max - xAxis.min;
rangeY = yAxis.max - yAxis.min;
xAxis.setExtremes(x - rangeX / 10, x + rangeX / 10, false);
yAxis.setExtremes(y - rangeY / 10, y + rangeY / 10, false);
chart.redraw();
chart.clickedOnce = true;
} else {
chart.zoomOut();
chart.clickedOnce = false;
}
}
}
}
Demo:
https://jsfiddle.net/BlackLabel/fxm812k4/
API reference:
https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
https://api.highcharts.com/class-reference/Highcharts.Chart#zoomOut
https://api.highcharts.com/highcharts/chart.events.click
Using a customEvents plugin (see: https://github.com/blacklabel/custom_events) and adding plotBand on the whole chart area you can register a callback on click and double click events. Using this approach you can make a zoom in on click event and zoom out on double click (not working on mobile devices).
Demo:
https://jsfiddle.net/BlackLabel/6tpb5q2z/

Is it possible to make all-custom point marker design in highstock?

I need my chart to have a pulsating last point.
I have dynamically updated chart http://jsfiddle.net/jswbouaa/
chart: {
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
}, 1000);
}
}
},
and a CSS-animated point https://codepen.io/anon/pen/rpwqOg?editors=1100#0
Is it possible to implement this animated point into the chart?
Yes. See this demo: http://jsfiddle.net/kkulig/zaeas1aw/
I created the marker using SVGRenderer.text(). Then I wrote function called positionMarker which is responsible for changing the position of the marker. I call it once after the data is set initially and after each point addition:
function positionMarker(series) {
var lastPoint,
chart = series.chart,
lastPoint = series.points[series.points.length - 1];
chart.pulseMarker.animate({
x: lastPoint.plotX - chart.plotLeft - chart.spacing[0],
y: lastPoint.plotY + chart.plotTop + chart.spacing[2] - 3
}, true);
}
(...)
load: function() {
var chart = this;
chart.pulseMarker = this.renderer.text("<span class='mgo-widget-call_pulse'></span>", 200, 200, true).add();
// set up the updating of the chart each second
var series = this.series[0];
// change the position of pulse marker
positionMarker(series);
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
// change the position of pulse marker
positionMarker(series);
}, 1000);
}
}
API reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text

highcharts column animation when adding point (series.addPoint())

I would like to change/customize highcharts' animation when adding new point.
series.addPoint([x, y], true, false);
Here is an example of hightcharts' default animation :
http://jsfiddle.net/pe4csrr7/
On click on a button (next or prev) you can see that the new bars appears behind the last one.
Instead of this default animation, I would like to see the bars coming from outside the graph. Here is an example of what I want : http://jsfiddle.net/smsducrg/ (Warning : the animations of this example is not always the same, after a while the default animation will come back, I don't know why...)
Thanks.
Maybe instead of using chart.redraw() you can use xAxis.setExtremes() for redrawing your chart.
http://api.highcharts.com/highcharts/Axis.setExtremes
I think that with small trick you will be able to achieve what you would like to.
$(function() {
var chart = $('#container').highcharts({
chart: {
type: 'column'
},
xAxis: {
categories: ['0', '1', '2', '3', '4', '5', '6']
},
series: [{
data: [1, 1, 1, 1, 1, 1, 1],
cropThreshold:0
}]
});
$('#prev').attr('start', 0);
$('#next').attr('end', 6);
$('#prev').off('click').on('click', function() {
var next = parseInt($('#next').attr('end'), 10) - 1;
var prev = parseInt($('#prev').attr('start'), 10) - 1;
var chart = $('#container').highcharts();
chart.series[0].addPoint({
x: prev,
y: 1
}, false, false);
chart.xAxis[0].setExtremes(prev + 1, next)
chart.xAxis[0].setExtremes(prev, next)
$('#next').attr('end', next);
$('#prev').attr('start', prev);
});
$('#next').off('click').on('click', function() {
var next = parseInt($('#next').attr('end'), 10) + 1;
var prev = parseInt($('#prev').attr('start'), 10) + 1;
var chart = $('#container').highcharts();
chart.series[0].addPoint({
x: next,
y: 1
}, false, true);
chart.xAxis[0].setExtremes(prev, next - 1)
chart.xAxis[0].setExtremes(prev, next)
$('#next').attr('end', next);
$('#prev').attr('start', prev);
});
});
You need to add bigger cropThreshold than default if you want to have this animation also after many button clicks (so for example when you will add 50 points).
Here you can see an example how it can work: http://jsfiddle.net/pe4csrr7/5/

How to display only last point on highcharts and that point should travel with chart line?

I have a area chart which is having a dynamic point that will be added to chart.I got this http://jsfiddle.net/rjpjwve0/
but it looks like the point gets displayed first and then after a delay the chart draws back. Now i want to display the last point which will be a animated point and it should travel with chart without delay in rendering.
Could any one help me to achieve this.
I put together a test, and it seems to work well.
I updated the load event to add a second series, using the same series.data[len -1] values; then in the setInterval portion, we update that new point at each iteration.
That way, by updating the existing marker rather than destroying one marker and creating another, the animation works as desired.
Code:
events: {
load: function () {
var series = this.series[0],
len = series.data.length;
//-------------------------------------
//added this part ->
this.addSeries({
id: 'end point',
type: 'scatter',
marker: {
enabled:true,
symbol:'circle',
radius:5,
fillColor:'white',
lineColor: 'black',
lineWidth:2
},
data: [[
series.data[len - 1].x,
series.data[len - 1].y
]]
});
var series2 = this.get('end point');
//-------------------------------------
setInterval(function () {
var x = (new Date()).getTime(),
y = Math.random();
len = series.data.length;
series.addPoint([x,y], true, true);
//and added this line -->
series2.data[0].update([x,y]);
}, 1000);
}
}
Fiddle:
http://jsfiddle.net/jlbriggs/a6pshutt/
You can try this :
series: [{
name: 'Random data',
marker : {
enabled : false,
lineWidth: 0,
radius: 0
},
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
}())
}]
Its works.
Greg.

Highstock marker specific option ignored

I'm wondering if there is a way to apply dynamic settings to individual marker of an highstock chart? I've searched for half a day and I have the feeling that there is a problem with the API. It seems that there is no ways to adjust marker setting on a specific datum. ex:
$('#container').highcharts('StockChart', {
chart : {
events : {
load : function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
}, 1000);
}
}
},
series : [{
data : (function () {
var data = [], time = (new Date()).getTime(), i;
for (i = -999; i <= 0; i += 1) {
data.push([
{ x: time + i * 1000,
y: Math.round(Math.random() * 100),
marker:{
fillColor:'red'
}
}
]);
}
return data;
}())
}]
}
I've fork a basic Highstock demo to illustrate my point. See the jsfiddle that demonstrate the problem: http://jsfiddle.net/9xj0nz72/1/
Maybe I have an error in my fiddle... or may I have to create an issue on Github?
Thanks a lot!!
I had to assign the style in the addPoint method, you can't just push to the data array. And you have to use it on the chart = new Highcharts.StockChart() variable.
I'm pretty sure I got what you were hoping for using the following. And to demonstrate I assigned a random color and radius to each new point.
$(function () {
var chart = new Highcharts.StockChart({
chart: {
renderTo: 'container'
},
plotOptions: {
series: {
marker: {
enabled: true
}
}
},
series: [{
name: 'Random data',
data: [],
time: (new Date()).getTime()
}]
});
/* add new random point every 1 second */
var i = 0;
setInterval(function () {
i++;
chart.series[0].addPoint({
marker: {
/* assign a random hex color and radius */
fillColor: '#' + (Math.random() * 0xFFFFFF << 0).toString(16),
radius: Math.floor(Math.random() * 10) + 1
},
y: Math.random() * 100,
x: i * 1000,
}, true, false);
}, 1000);
});
Your updated JSFiddle

Categories