If I create column chart that has values that are > 0 but much closer in value to each other than they are to 0 then the chart generated will have columns that look almost identical. See this jsFiddle.
However if I change the chart type to a line then the resulting chart is much nicer because the min yAxis value is calculated to a non-zero value so that the distribution of the values on the chart is much more obvious.
I could manually set a min yAxis value but I need this to work for any set of data and so it needs to be calculated. How could I achieve the same thing for a column chart?
I've found where Highcharts calculates the min value for line charts (at least for linear axes). It's in the getTickPositions() function. Specifically these lines of code:
// pad the values to get clear of the chart's edges
if (!categories && !usePercentage && !isLinked && defined(min) && defined(max)) {
length = (max - min) || 1;
if (!defined(options.min) && !defined(userMin) && minPadding && (dataMin < 0 || !ignoreMinPadding)) {
min -= length * minPadding;
}
if (!defined(options.max) && !defined(userMax) && maxPadding && (dataMax > 0 || !ignoreMaxPadding)) {
max += length * maxPadding;
}
}
So it calculates the min as
length = ([max data value] - [min data value]) || 1
min = [min data value] - length * minPadding
The default for minPadding on the yAxis is 0.05 so
394.5 = 395 - ((405 - 395) * 0.05)
394.5 is rounded when creating the tick positions so the end result is 390.
What I've come up with so far is this. (The minPadding default on the yAxis doesn't seem to be exposed so I've hardcoded it)
var data = [400,405,395];
Array.max = function( array ){
return Math.max.apply( Math, array );
};
Array.min = function( array ){
return Math.min.apply( Math, array );
};
var min = Array.min(data);
var max = Array.max(data);
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'column'
},
yAxis: {
min: min - ((max-min) * 0.05)
},
series: [{
data: data
}]
});
Try setting the yAxis value, for example:
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'column'
},
yAxis: {
min: 390,
startOnTick: false
},
series: [{
data: [400,405,395]
}]
});
You can also set it to some kind of dynamic value in javascript (AVG(400, 405, 395) - 10%, for instance) that should give it enough scale.
Updated JSFiddle is here.
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
}
});
How show Ticker from the start of plot along with the label value?
I want the ticker to start at the plot and also show the correct value.
I set pointStart to start of the x-axis value.
When I set startOnTick to true. And for know tickIntervalto 30 minutes. (tickInterval varies based on the data interval)
this is what I get.
Any way to show the ticker at the start of the plot.
Use the tickPositioner function, for example:
xAxis: {
type: 'datetime',
startOnTick: true,
labels: {
formatter: function() {
return Highcharts.dateFormat('%k:%M', this.value);
}
},
tickPositioner: function() {
var ticks = [],
dataMin = this.dataMin,
dataMax = this.dataMax,
tickInterval = (dataMax - dataMin) / 5;
for (var i = this.dataMin; i <= this.dataMax; i += tickInterval) {
ticks.push(i);
}
return ticks;
}
}
Live demo: http://jsfiddle.net/BlackLabel/aswzfrnc/
API Reference:
https://api.highcharts.com/highcharts/xAxis.tickPositioner
https://api.highcharts.com/class-reference/Highcharts#.dateFormat
I would like to ask if somebody knows how to set X axis in Highcharts to time. My aplication is taking data from database and the frequency of the samples is 250ms. I want the X axis not to show counted values but something like time. I render 2500 values at once so that means 10 secs. The best would be to have on X axis and a mark there every 0.5 sec that means every 125 samples a mark. Like (0 samples = 0 sec);(125 samples = 0,5 sec);(500 samples = 1 sec);(725 samples = 1.5 sec)
Thank you for your opinions.....
chart () {
var options = {
chart: {
renderTo: 'services',
type: 'line',
animation: 'false'
},
plotOptions: {
series: {
animation: {
duration: 10000
}
}
},
series: [{marker: {
enabled: false
}}]
};
You can supply a custom label formatter. For example...
xAxis: {
labels: {
formatter: function () {
return (baseTime + (this.value / 500)) + " sec";
}
}
},
where baseTime is the time of the first data point.
Documentation for custom label formatter can be found at...
http://api.highcharts.com/highcharts#xAxis.labels.formatter
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 need change first tick label on yAxis. I changed the minimum value on the yAxis:
yAxis: [{
title : {
text : 'Position'
},
gridLineWidth: 1,
startOnTick: false,
min: 1, //changed min value
reversed: true,
}]
but the value is not shown in front yAxis. How to sign the first value in the yAxis?
Here's my chart.
if I write:
yAxis: [{
title : {
text : 'Позиция'
},
startOnTick: false,
showFirstLabel: true,
min: 1,
reversed: true,
tickInterval: 1,
labels: {
formatter: function() {
if (this.value < 1)
return null;
else if (this.value == 1)
return this.value;
else if (this.value % 2 == 0)
return this.value;
}
}
}]
then scaling yAxis turns bad for my data :( chart
You can define your own yAxis.tickPositioner to define all positions where you wish a tick should be placed.
Since in your case you don't want to override the entire behavior, but just place a tick at the min position, you can leverage the axis.getLinearTickPositions(interval, min, max) method to get the array of default positions that would be otherwise generate, and then append your additional ticks to this array.
The code below has ticks added on both the min and max of the y-axis
yAxis: {
showFirstLabel: true,
showLastLabel: true,
tickPositioner: function(min, max) {
// specify an interval for ticks or use max and min to get the interval
var interval = Math.round((max - min) / 5);
var dataMin = this.dataMin;
var dataMax = this.dataMax;
// push the min value at beginning of array
var positions = [dataMin];
var defaultPositions = this.getLinearTickPositions(interval, dataMin, max);
//push all other values that fall between min and max
for (var i = 0; i < defaultPositions.length; i++) {
if (defaultPositions[i] > dataMin && defaultPositions[i] < dataMax) {
positions.push(defaultPositions[i]);
}
}
// push the max value at the end of the array
positions.push(dataMax);
return positions;
}
}
Show tick on min and max of y axis | Highchart & Highstock # jsFiddle
Demo of your chart # jsFiddle
For me it seems everything is working fine. The minimum value of your reversed chart is 1, which is right on top of the y-Axis. However if you want to show this value on the axis, have a look at this post for a description.