I'm using an updating spline chart to show a line that changes each second. The changing is set in chartinfo.chart.events.load. Below is the code I'm using in my actual program:
chartinfo.chart.events.load: function() {
powerLine = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = ((latestPowerValue > maxPower) ? maxPower : ((latestPowerValue < minPower) ? minPower : latestPowerValue)); //Math.random() * 250;
powerLine.addPoint([x, y], true, true);
}, 1000);
}
I have another updating spline chart to show two lines which also changes each second. This is almost the same as the above example but this time two series are updated.
chartinfo.chart.events.load: function() {
var minLine = this.series[0];
var maxLine = this.series[1];
setInterval(function() {
var x = (new Date()).getTime();
var ymin = ((latestVoltageMin > maxVoltage) ? maxVoltage : ((latestVoltageMin < minVoltage) ? minVoltage : latestVoltageMin));
var ymax = ((latestVoltageMax > maxVoltage) ? maxVoltage : ((latestVoltageMax < minVoltage) ? minVoltage : latestVoltageMax));
minLine.addPoint([x, ymin], true, true);
maxLine.addPoint([x, ymax], true, true);
}, 1000);
};
I have also prepared working examples of the single lined (working) graph and the double lined (not working) graph in jsFiddle.
I'd like to find out how to get the double lined graph to move/slide like the single lined graph. Any help or insight into the problem is welcome!
Set the first add point's animate parameter to false, the second add point will animate for the both of them.
series.addPoint([x, y], false, true);
series2.addPoint([x, y2], true, true);
jsFiddle
In addition to
series.addPoint([x, y], false, true);
series2.addPoint([x, y2], true, true);
also write chart.redraw(); after series2.addPoint([x, y2], true, true);
This makes it work for me in webapp
Related
I am trying to create a stock performance chart, very similar to this chart:
https://www.orbis.com/bm/private-client/funds/global-equity
The idea is that the y-axis always starts at 10,000 and moves from there. When the navigator range changes, the top area is redrawn by applying a factor to all the data points. And even though the chart changes, the navigator area does not change.
Any ideas on how to do this with highstock?
Thanks to #ppotaczek for the answer. It was simpler than I was trying to make it. Simplicity is genius.
This is the solution
const baseData = [100.00, 99.78, 96.50, 96.61, 97.57, 96.02, 96.42, 99.17, 100.35, 101.30, 100.92, 99.63, 97.90, 100.30, 91.66, 94.61, 95.36, 94.89, 95.43, 95.25, 96.70, 93.58, 92.53];
[100, 100.95, 100.57, 99.28, 97.56, 99.95, 91.34, 94.28, 95.03, 94.56, 95.1, 94.92]
Highcharts.stockChart('container', {
series: [{
data: baseData.slice()
}],
xAxis: {
events: {
afterSetExtremes: function(e) {
const min = e.min;
const max = e.max;
const visibleData = baseData.filter(
(dataEl, index) => index > min && index <= max + 1
);
factor = 100.00/visibleData[0];
const finalData = [];
visibleData.forEach((dataEl, index) => {
finalData.push([min + index, dataEl*factor]);
});
this.series[0].setData(finalData);
}
},
minRange: 1
},
navigator: {
adaptToUpdatedData: false
}
});
I want to make stacked bar chart where each portion has a width that encodes one value (say "Change" in the data below) and a height that encodes another value ("Share")
In some ways this is like a histogram with different bin sizes. There are a few "histogram" questions but none seem to address this. Plot Histograms in Highcharts
So given data like this:
Category Share Price Change
Apples 14.35 0.1314192423
Horseradish 46.168 0.1761474117
Figs 2.871 0.018874249
Tomatoes 13.954 0.0106121298
Mangoes 7.264 0.1217297011
Raisins 5.738 0.0206787136
Eggplant 6.31 0.0110160732
Other produce 3.344 0.0945377722
I can make a stacked bar that captures the "share" column in widths:
And another that captures the "change" column in heights:
And I can use an image editor to combine those into this histogram-like beast:
Which really captures that horseradish is a huge deal. So my question is, can I do that within Highcharts?
You can realise that by using snippet.
(function (H) {
var seriesTypes = H.seriesTypes,
each = H.each,
extendClass = H.extendClass,
defaultPlotOptions = H.getOptions().plotOptions,
merge = H.merge;
defaultPlotOptions.marimekko = merge(defaultPlotOptions.column, {
pointPadding: 0,
groupPadding: 0
});
seriesTypes.marimekko = extendClass(seriesTypes.column, {
type: 'marimekko',
pointArrayMap: ['y', 'z'],
parallelArrays: ['x', 'y', 'z'],
processData: function () {
var series = this;
this.totalZ = 0;
this.relZ = [];
seriesTypes.column.prototype.processData.call(this);
each(this.zData, function (z, i) {
series.relZ[i] = series.totalZ;
series.totalZ += z;
});
},
translate: function () {
var series = this,
totalZ = series.totalZ,
xAxis = series.xAxis;
seriesTypes.column.prototype.translate.call(this);
// Distort the points to reflect z dimension
each(this.points, function (point, i) {
var shapeArgs = point.shapeArgs,
relZ = series.relZ[i];
shapeArgs.x *= (relZ / totalZ) / (shapeArgs.x / xAxis.len);
shapeArgs.width *= (point.z / totalZ) / (series.pointRange / series.xAxis.max);
});
}
});
}(Highcharts));
Example: http://jsfiddle.net/highcharts/75oucp3b/
I'm trying to set the min zoom (max range) of my chart. Basically I'm trying to do the opposite of the minRange property. I'm struggling for a while with this problem. I have a "solution", but I don't like it, this solution allow the user to choose a range greater then the "max range", and immediately correct it.
POSSIBLE SOLUTION
$(function() {
var lastMin;
var lastMax;
var maxRange = 12 * 30 * 24 * 3600 * 1000; //12 month
$('#container').highcharts('StockChart', {
scrollbar: {
liveRedraw: false
},
xAxis: {
events: {
afterSetExtremes: function(e) {
var max = this.max,
min = this.min;
if (lastMin && lastMax) {
if(max-min > maxRange) {
if (min < lastMin) {
min = max - maxRange;
} else {
max = min + maxRange;
}
}
}
var x = this;
setTimeout(function(){
x.setExtremes(min,max); //chart xAxis
}, 1);
lastMin = min;
lastMax = max;
}
}
},
rangeSelector: {
selected: 1
},
series: [{
name: 'USD to EUR',
data: usdeur
}]
});
});
I want to block the user from choosing a range greater than the allowed, in other words, block the navigator when it's too big
I'm also following this issue, I tried all the proposed solution, but I'm having errors ("Uncaught ReferenceError: Highcharts is not defined")
Thanks Sebastian!
I managed to find a solution (fiddle) wrapping the "render" function. Doing that I managed to really set a "min zoom" on the navigator bar.
$(function() {
var lastX0;
var lastX1;
var maxRange = 100; //100 pixels
(function (H) {
H.wrap(H.Scroller.prototype, 'render', function (proceed) {
console.log(arguments)
if(arguments[4] - arguments[3] > maxRange + 2) {
if (arguments[3] < lastX0) {
arguments[3] = lastX0;
} else {
arguments[4] = lastX1;
}
}
proceed.apply(this, [].slice.call(arguments, 1));
lastX0 = arguments[3];
lastX1 = arguments[4];
});
}(Highcharts));
$('#container').highcharts('StockChart', {
scrollbar: {
liveRedraw: true
},
series: [{
name: 'USD to EUR',
data: usdeur
}]
});
var highchart = $('#container').highcharts();
var extremes = highchart.xAxis[0].getExtremes();
var rangeTotal = extremes.max - extremes.min;
var f = maxRange / $('#container').width();
highchart.xAxis[0].setExtremes(extremes.max - (f * rangeTotal), extremes.max);
});
In the sample code I'm used a fixed amount of pixels, but in my real application i'm making it dynamic. I making this, because I can't use the data grouping property in the software that I'm working, and since the minimum size of a bar in a chart is 1 pixel (obviously) highcharts hide some bars (or points).
I'm setting the minimum zoom so all bar in the displayed range are visible , since the user can't display a higher range in the x Axis the "hidden" bar "problem" (is an awesome feature, but I can't make use of it) won't happen
I have a line chart which dynamically updates. I want to add a marker at the last point. As the chart scrolls and new points are added, I want to remove the previous marker and add it to the most recent point. Thus the "tip" of this line chart will only have a marker.
Any help would be greatly appreciated.
You can disable markers in the plotOptions, and then for the point that you want the marker to appear on, set the data as an object, like this:
http://jsfiddle.net/jlbriggs/JVNjs/281/
data: [7,12,16,32,{y:64,marker:{enabled:true,radius:5,fillColor:'#c00'}}]
You can disable marker for each point except the last one.
On start:
series: [{
name: 'Random data',
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(),
marker: {
enabled: i === 0
}
});
}
return data;
}())
}]
And disabling marker in the last point before the new point is added:
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.random();
series.data[series.data.length - 1].update({
marker: { enabled: false }
}, false)
series.addPoint([x, y], true, true);
}, 1000);
}
}
You could try this.
http://jsfiddle.net/687215jj/2/
If you open this JSFiddle with the dynamic spline update it loads the series with 20 points before it starts updating every second.
Example
I don't want to display any initial data and let the interval add the points as they come in.
So I change:
series: [{
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
})()
}]
to
series: [{
name: 'Random data',
data: []
}]
But it doesnt add the points. Is there something I am missing?
Change your load function so that the shift parameter doesn't apply before you've added your 20 values, see this jsfiddle
load: function() {
// set up the updating of the chart each second
var series = this.series[0],
maxSamples = 20,
count = 0;
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint(
[x,y]
, true
, (++count >= maxSamples)
);
}, 1000);
}
The third parameter of addPoint is set if you what to shift a point after add this one.
So, what is happening ?
You're adding a point and then removing it.
Change:
series.addPoint([x, y], true, true);
To:
series.addPoint([x, y], true);
Demo
Reference
http://api.highcharts.com/highstock#Series.addPoint()