Reputation: 181
I am trying to use a logarithmic scale on my chart like below:
However, the outbound data is much lower than the inbound data. This doesnt show properly in the graph and makes it look like there is actually more outbound data than inbound.
I would like to have a linear scale upto the max value of the y axis (136) and some additional offest so basically upto 150 it should display linear scale and from there upto 600 (which shows the max capacity marker) to be logarithmic. Is this at all possible with Highcharts? Maybe the best function to use would be tickPositioner http://api.highcharts.com/highcharts#yAxis.tickPositioner.
The final desired result should be something like this:
Upvotes: 2
Views: 2274
Reputation: 2066
For anyone with a similar problem, update for 2024:
Add this before you create the chart:
(function (H) {
H.addEvent(H.Axis, 'afterInit', function() {
const logarithmic = this.logarithmic;
if (logarithmic){
logarithmic.positiveValuesOnly = false;
const scale = (num, in_min, in_max, out_min, out_max) => {
return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
const defaultGetLogTickPositions = logarithmic.getLogTickPositions;
const defaultLog2lin = logarithmic.log2lin;
const defaultLin2log = logarithmic.lin2log;
const customTicks = this.options.customTicks;
logarithmic.getLogTickPositions = function (interval, min, max, minor) {
if (customTicks) {
let interval = customTicks[customTicks.length - 1] / (customTicks.length - 1);
return customTicks.map((v, i) => i * interval)
}
else {
return defaultGetLogTickPositions(interval, min, max, minor);
}
};
logarithmic.log2lin = function (num) {
if (customTicks) {
let tickInterval = ( customTicks[customTicks.length-1] / ( customTicks.length - 1 ) );
for (let i = 0; i < customTicks.length - 1; i++) {
if (num <= customTicks[i+1]) {
return scale(num, customTicks[i], customTicks[i+1], i * tickInterval, (i + 1) * tickInterval )
}
}
return 0;
}
else {
return defaultLog2lin(num);
}
};
logarithmic.lin2log = function (num) {
if (customTicks) {
let tickInterval = ( customTicks[customTicks.length-1] / ( customTicks.length - 1 ) );
for (let i = 0; i < customTicks.length - 1; i++) {
if (num <= tickInterval * (i + 1)) {
return scale(num, i * tickInterval, (i + 1) * tickInterval, customTicks[i], customTicks[i+1] )
}
}
}
else {
return defaultLin2log(num);
}
};
}
});
}(Highcharts));
Now on your chart initialization, use this for yAxis:
{
type: 'logarithmic',
customTicks: [0,20,40,60,80,100,120,140,160,400,600] //modify according to your data
}
Upvotes: 0
Reputation: 108522
Well, this is certainly a messy solution, but you could composite two graphs together:
Fiddle here.
$(function () {
$('#containerBot').highcharts({
chart: {marginTop: 1},
title: {margin: 0, text: ''},
yAxis: {max: 100},
exporting: {enabled: false},
series: [{
name: 'One',
data: [70.0, 60.9, 90.5, 140.5, 180.2, 210.5, 205.2, 260.5, 230.3, 180.3, 130.9, 90.6]
}, {
name: 'Two',
data: [-0.2, 0.8, 50.7, 110.3, 170.0, 220.0, 240.8, 204.1, 200.1, 140.1, 80.6, 20.5]
}]
});
$('#containerTop').highcharts({
chart: {marginBottom: -1},
title: {text: 'My Chart'},
yAxis: {min: 100},
xAxis: {labels: {enabled: false}},
legend: {enabled: false},
exporting: {enabled: false},
credits: {enabled: false},
series: [{
name: 'One',
data: [70.0, 60.9, 90.5, 140.5, 180.2, 210.5, 205.2, 260.5, 230.3, 180.3, 130.9, 90.6]
}, {
name: 'Two',
data: [-0.2, 0.8, 50.7, 110.3, 170.0, 220.0, 240.8, 204.1, 200.1, 140.1, 80.6, 20.5]
}]
});
});
Upvotes: 2