Highcharts live chart shifts continuously - highcharts

I have the following issue:
I initialize the chart with null values because I don't have meaningful initial values.
I add points with addPoint after getting the data through ajax
The problem is that the chart shifts continuously and not just on the end of the time range.
I use the code:
generateInitialData = function() {
var initialData = [];
var time = (new Date()).getTime();
var i;
for (i = -99; i <= 0; i++) {
initialData.push([time + i * 3000,null]);
}
return initialData;
}
addPoint = function(){
var max = 1000;
var min = 300;
var value = Math.floor(Math.random() * (max - min + 1)) + min;
chart.series[0].addPoint([(new Date()).getTime(), value], true, true);
}
$('#container').highcharts({
chart: {
type: 'line',
},
xAxis: {
type: 'datetime',
minRange:1000 * 60 * 5,
maxRange:1000 * 60 * 5
}
});
var chart = $('#container').highcharts();
chart.addSeries({"name": "example","data":generateInitialData()});
setInterval(addPoint,3000);
Please see jsFiddle demo of the issue :
http://jsfiddle.net/wXmLQ/7/
Please help
Tali

You don't need to set null data from the beginning, instead of that you can just addd one empty point and just check if you want to shift or not, see: http://jsfiddle.net/Fusher/wXmLQ/8/
addPoint = function(){
var max = 1000;
var min = 300;
var value = Math.floor(Math.random() * (max - min + 1)) + min;
var len = chart.series[0].data.length;
chart.series[0].addPoint([(new Date()).getTime(), value], len < 99);
}
$('#container').highcharts({
chart: {
type: 'line',
},
xAxis: {
type: 'datetime',
minTickInterval: 1000 * 60, //one minute
minRange:1000 * 60 * 5,
maxRange:1000 * 60 * 5
}
});
var chart = $('#container').highcharts();
chart.addSeries({"name": "example","data":[[+new Date(), null]]});
setInterval(addPoint,3000);

The addPoint and addSeries methods have a re-draw parameter that defaults to true. Make this parameter false whenever you call an updating method
chart.series[0].addPoint([(new Date()).getTime(), value], false);
chart.addSeries({"name": "example","data":generateInitialData()}, false);
Then once you've made all the updates, explicitly redraw the chart
chart.redraw();

Related

Highcharts - Markers in line charts move up when leaving hovering

I am trying to use Font Awesome icons as markers in HighCharts line chart. With help from fellow developers on Stack Overflow, I have managed to do that. One problem left is that now, whenever I hover over the markers and then leave hovering, they just move up a bit from the line and stay there forever. I really have no idea why.
This is the fiddle: https://jsfiddle.net/vf0g4u5k/12/. Appreciate any help.
The plug-in to use Font Awesome with HighCharts
(function (H) {
function symbolWrap(proceed, symbol, x, y, w, h, options) {
if (symbol.indexOf('text:') === 0) {
var text = symbol.split(':')[1],
svgElem = this.text(text, x, y + h)
.css({
fontFamily: '"Font Awesome 5 Free"',
fontSize: (h * 2 ) + "px"
});
if (svgElem.renderer.isVML) {
svgElem.fillSetter = function (value, key, element) {
element.style.color = H.Color(value).get('rgb');
};
}
return svgElem;
}
if (symbol.indexOf('textn:') === 0) {
var text = symbol.split(':')[1],
svgElem = this.text(text, x, y + h)
.css({
fontFamily: '"Font Awesome 5 Free"',
fontSize: (h * 2 ) + "px",
fontWeight: 900
});
if (svgElem.renderer.isVML) {
svgElem.fillSetter = function (value, key, element) {
element.style.color = H.Color(value).get('rgb');
};
}
return svgElem;
}
return proceed.apply(this, [].slice.call(arguments, 1));
}
H.wrap(H.SVGRenderer.prototype, 'symbol', symbolWrap);
if (H.VMLRenderer) {
H.wrap(H.VMLRenderer.prototype, 'symbol', symbolWrap);
}
// Load the font for SVG files also
H.wrap(H.Chart.prototype, 'getSVG', function (proceed) {
var svg = proceed.call(this);
svg = '<?xml-stylesheet type="text/css" ' +
'href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" ?>' +
svg;
return svg;
});
}(Highcharts));
I ended up doing like this. Posting in case it may help someone else.
point: {
events: {
mouseOut: function() {
var index = this.index
for( var series of this.series.chart.series){
for(var j=0;j<series.points.length;j++){
if(j === index && series.points[j].graphic){series.points[j].graphic.attr({'translateY': 8})}
}
};
}
}
}
You can adjust your custom marker settings by setting translateX and translateY like this
var text = symbol.split(':')[1],
svgElem = this.text(text, x, y)
.attr({
translateY: h,
translateX: -1
})
.css({
fontFamily: '"Font Awesome 5 Free"',
fontSize: (h * 2 ) + "px"
});

Highcharts: How we can sort series with animation?

I am using horizontal bar chart with continuous update of series data. This is achieved successfully, but now i want these series to be sorted on data (continuously with every update of series) in desc order with animation. I mean when a bar get max value then move it to the top with animation.
how can i achieve this?
That type of functionality is not supported by default in Highcharts. Below you can find an example that shows how you can achieve the wanted result by custom code:
var options = {
chart: {
type: 'bar'
},
xAxis: {
categories: ['Cat1', 'Cat2', 'Cat3'],
},
series: [{
data: [1000, 900, 800]
}]
};
var chart = Highcharts.chart('container', options);
// Add custom data labels
chart.series[0].points.forEach(function(point, i) {
var x = chart.plotWidth - point.plotY + chart.plotLeft,
y = chart.xAxis[0].ticks[i].label.xy.y;
point.customDataLabel = chart.renderer.text(
point.y,
x,
y
)
.css({
color: '#000000',
fontSize: '14px'
})
.attr({
zIndex: 3
})
.add();
setAlign(point.customDataLabel);
});
function setAlign(label, xPos) {
var align = 'left',
bbox = label.getBBox();
if (chart.chartWidth < (xPos ? xPos : bbox.x + bbox.width) + 50) {
align = 'right';
}
label.attr({
align: align
})
}
var update = function() {
var points = chart.series[0].points;
chart.series[0].setData([Math.round(Math.random() * 1000), Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)]);
};
var rotate = function() {
var points = chart.series[0].points,
labelX,
ticks = chart.xAxis[0].ticks;
var sortedPoints = points.slice();
sortedPoints.sort(function(a, b) {
return b.y - a.y;
});
points.forEach(function(point, i) {
sortedPoints.forEach(function(sPoint, j) {
if (point === sPoint) {
labelX = chart.plotWidth - points[i].plotY + chart.plotLeft;
// Animate the column
points[i].graphic.animate({
x: points[j].shapeArgs.x
});
// Animate the label
points[i].customDataLabel.attr({
text: points[i].y
}).animate({
y: ticks[j].label.xy.y,
x: labelX
});
setAlign(points[i].customDataLabel, labelX);
// Animate the axis label
ticks[i].label.animate({
y: ticks[j].label.xy.y
});
}
});
});
};
document.getElementById("button").addEventListener("click", function() {
update();
rotate();
}, false);
Live demo: https://jsfiddle.net/BlackLabel/mg5bv3s8/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGElement#animate

highcharts <path> attribute d: Expected number

The running caseI met a problem in customizing a dynamic update chart. here is my code.
load : function () {
var series = this.series[0];
time2 = setInterval(function () {
var flag = true;
if ($('#pause:checked').length > 0) flag = false;
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
xValue = x;
yValue = y;
series.addPoint([x, y], flag, flag);
console.log(xValue + ", " + yValue);
if(flag){
document.getElementById("currentFrequency").innerHTML = (x + " ");
document.getElementById("currentDb").innerHTML = (y + " ");
document.getElementById("currentFrequency2").innerHTML = (x);
}
}, 100);
}, // -> function load over
The error says: highstock.js:59 Error: attribute d: Expected number, "…0.5325987144169 C 0 20.532598714…".
The way generating the random data is exactly the same way as what was showing in the official demo. The problem is likely to occur when set the interval lower than 1000.
Anyone can figure out what went wrong? thanks a lot.

Is possible to have a Title (on axis) that rotates when draggable box (3d) rotate?

I'm trying to change some things in the graphic "3D scatter chart Draggable Box"
http://www.highcharts.com/demo/3d-scatter-draggable/grid-light
Is possible to add a title to an axis, but that it rotates when I turn the box?
Now, if i add a title in this way:
yAxis: {
title: {
text: "Latitude"
}
},
When i rotate the box, the title doesn't follow the yAxis....
This is the code to rotate the chart:
$(chart.container).bind('mousedown.hc touchstart.hc', function (e) {
e = chart.pointer.normalize(e);
var posX = e.pageX,
posY = e.pageY,
alpha = chart.options.chart.options3d.alpha,
beta = chart.options.chart.options3d.beta,
newAlpha,
newBeta,
sensitivity = 5; // lower is more sensitive
$(document).bind({
'mousemove.hc touchdrag.hc': function (e) {
// Run beta
newBeta = beta + (posX - e.pageX) / sensitivity;
newBeta = Math.min(100, Math.max(-100, newBeta));
chart.options.chart.options3d.beta = newBeta;
// Run alpha
newAlpha = alpha + (e.pageY - posY) / sensitivity;
newAlpha = Math.min(100, Math.max(-100, newAlpha));
chart.options.chart.options3d.alpha = newAlpha;
window.alphaOn3dGraph = newAlpha;
window.betaOn3dGraph = newBeta;
chart.redraw(false);
},
'mouseup touchend': function () {
$(document).unbind('.hc');
}
});
});

Highcharts / Highstock step line without vertical "transition" lines?

Is it possible to omit the vertical lines from the "square wave" line? I think you could call that a level line, here's an illustration:
The easiest way to achieve this look is to use a scatter chart with a custom "line" symbol:
// define a custom line symbol
Highcharts.SVGRenderer.prototype.symbols.line = function (x, y, w, h) {
return ['M', x, y, 'L', x - w * 2, y, 'M', x, y, 'L', x + w * 2, y, 'z'];
};
if (Highcharts.VMLRenderer) {
Highcharts.VMLRenderer.prototype.symbols.cross = Highcharts.SVGRenderer.prototype.symbols.cross;
}
$('#container').highcharts({
chart: {
type: 'scatter'
},
title: {
text: 'Look At Lines!!'
},
series: [{
name: 'Line Symbol',
data: [54.4, 29.9, {y: 129.2, radius: 8}, 144.0, 176.0, 135.6],
marker: {
symbol: 'line',
lineColor: null,
lineWidth: 2
}
}]
});
Note that you can adjust the length of an individual point by upping the radius.
Fiddle here.
Produces:
While above answer works fine, the issue I faced was that width of the line symbol is not the same as column width when displayed in combination with a column chart.
example image
Another option is to extend column type chart in a new chart type like so:
$(function () {
(function (H) {
var each = H.each,
pick = H.pick,
Series = H.Series,
seriesType = H.seriesType;
seriesType('floatingStep', 'column', {
fixedPointLength: 2
}, /** #lends seriesTypes.floatingStep.prototype */ {
/**
* Translate each point to the plot area coordinate system and find shape positions
*/
translate: function () {
var series = this,
chart = series.chart,
options = series.options,
dense = series.dense = series.closestPointRange * series.xAxis.transA < 2,
borderWidth = series.borderWidth = pick(
options.borderWidth,
dense ? 0 : 1 // #3635
),
yAxis = series.yAxis,
threshold = options.threshold,
translatedThreshold = series.translatedThreshold = yAxis.getThreshold(threshold),
minPointLength = pick(options.minPointLength, 5),
fixedPointLength = options.fixedPointLength,
metrics = series.getColumnMetrics(),
pointWidth = metrics.width,
seriesBarW = series.barW = Math.max(pointWidth, 1 + 2 * borderWidth), // postprocessed for border width
pointXOffset = series.pointXOffset = metrics.offset;
if (chart.inverted) {
translatedThreshold -= 0.5; // #3355
}
// When the pointPadding is 0, we want the columns to be packed tightly, so we allow individual
// columns to have individual sizes. When pointPadding is greater, we strive for equal-width
// columns (#2694).
if (options.pointPadding) {
seriesBarW = Math.ceil(seriesBarW);
}
Series.prototype.translate.apply(series);
// Record the new values
each(series.points, function (point) {
var yBottom = pick(point.yBottom, translatedThreshold),
safeDistance = 999 + Math.abs(yBottom),
plotY = Math.min(Math.max(-safeDistance, point.plotY), yAxis.len + safeDistance), // Don't draw too far outside plot area (#1303, #2241, #4264)
barX = point.plotX + pointXOffset,
barW = seriesBarW,
barY = Math.min(plotY, yBottom),
up,
barH = Math.max(plotY, yBottom) - barY;
// Handle options.minPointLength
if (Math.abs(barH) < minPointLength) {
if (minPointLength) {
barH = minPointLength;
up = (!yAxis.reversed && !point.negative) || (yAxis.reversed && point.negative);
barY = Math.abs(barY - translatedThreshold) > minPointLength ? // stacked
yBottom - minPointLength : // keep position
translatedThreshold - (up ? minPointLength : 0); // #1485, #4051
}
}
if (fixedPointLength) {
barH = fixedPointLength;
}
// Cache for access in polar
point.barX = barX;
point.pointWidth = pointWidth;
// Fix the tooltip on center of grouped columns (#1216, #424, #3648)
point.tooltipPos = chart.inverted ? [yAxis.len + yAxis.pos - chart.plotLeft - plotY, series.xAxis.len - barX - barW / 2, barH] : [barX + barW / 2, plotY + yAxis.pos - chart.plotTop, barH];
// Register shape type and arguments to be used in drawPoints
point.shapeType = 'rect';
point.shapeArgs = series.crispCol.apply(
series,
point.isNull ?
// #3169, drilldown from null must have a position to work from
// #6585, dataLabel should be placed on xAxis, not floating in the middle of the chart
[barX, translatedThreshold, barW, 0] : [barX, barY, barW, barH]
);
});
},
});
})(Highcharts);
});
View in JS Fiddle

Resources