Set a minimal default range for a column chart in Highcharts - javascript

I'm using Highcharts for a column chart that has positive and negative percentage values.
I always want the y-axis of the chart to display at least the range between -50% and +30%, no matter what the values are. However, if a value is larger than 30% or small than -50% the range of the y-axis should adapt accordingly. if I use yAxis: {min: -50, max: 30} the range won't get bigger when I have larger values.
Is there a way to do this? Or do I have to update it programmatically once Highcharts has calculated the range?

Currently you have to do it yourself.
It can be accomplished by running a function to check the min/max and reset if needed.
Something like this (quick dirty example):
function setMinAxisExtremes(chart, axis, min, max) {
var ax = axis == 'y' ? chart.yAxis[0] : chart.xAxis[0];
var ext = ax.getExtremes();
min = ext.min > min ? min : ext.min;
max = ext.max < max ? max : ext.max;
ax.setExtremes(min,max);
}
Example:
http://jsfiddle.net/jlbriggs/szub0o3g/
(and as noted above, there is a feature request to have Highcharts do this with a built in property, which is sorely in need of votes, here: http://highcharts.uservoice.com/forums/55896-general/suggestions/1848953-extend-the-axis-max-property-to-act-like-css-mi )

You can prepare your own function to position ticks, it is tickPositioner

Related

HighCharts y-Axis set min max with input field on rendered graph axis

I'd like to give a users with HighCharts.chart the option set the min and max for y-Axis. This should be ux friendly. I thought a smart solution could be adding a min and max field to the y-axis. I'm open for better solutions, if there are any around?
I do know I can set min and max as a initial configuration with yAxis.min and yAxis.max, however could not find any configuration or plugin for allowing this to the user. Nor could I find a easy way to extend y-Axis or replace the min and max label with a form field.
How can I extend the y-Axis labels min and max with input field to change min and max for the corresponding plot?
UI idea:
I think that the below demo could be a good start to implement your requirement.
Demo: https://jsfiddle.net/BlackLabel/3y9au2h4/
var minInput = document.getElementById('minInput'),
maxInput = document.getElementById('maxInput');
minInput.onchange = function() {
chart.yAxis[0].update({
min: this.value
})
}
maxInput.onchange = function() {
chart.yAxis[0].update({
max: this.value
})
}
API: https://api.highcharts.com/class-reference/Highcharts.Axis#update
EDIT
Above labels could be rendered as standalone HTML elements and customized by using the formatter callback.
Demo: https://jsfiddle.net/BlackLabel/e60xj9go/
API: https://api.highcharts.com/highcharts/yAxis.labels.useHTML
API: https://api.highcharts.com/highcharts/yAxis.labels.formatter

How do I dynamically set the scale of y-axis for c3 chart?

I'm making a c3 chart that has grouped data, and I'd like to have a y-axis grid line that shows a maximum value, that the grouped data combined should not exceed.
So, the y-axis grid line could be called "Maximum"
I know how to make the grid, but it doesn't always show because the grouped data might be way below the grid value. But I want the grid to always show.
I looked at padding for the y-axis, but it's uses pixels and is hard to get accurate.
Is there a away to just set the y-axis to show like 5 values greater than whatever the y-axis grid line is?
Unfortunately, C3 does not have a setting for "set Y axis to maximum of yvalue or largest data". However, let's assume you have added a grid line using a method like below. You can then set the y-axis padding and maximum value using the settings shown here:
grid: {
y: {
lines: [{ value: 20 }],
}
},
axis: {
y: {
padding: {top:5, bottom,0},
max: 20
}
}
In this case I have set the max value to be the same as the gridline value and used padding to create a small space above it. This will handle the case where your data is below the gridline. However, if your data exceeds the (gridline+padding) total then the chart won't grow to accommodate that data because the max setting is fixed. So, you will need to dynamically change this max value using javascript if your data is greater than the max value by finding the maximum value in your data and setting max above that if it exceeds your gridline value, something like this...
if(highValue > gridlineValue)
chart.axis.max(highValue);
else
chart.axis.max(gridlineValue);
I just noticed that your data never exceeds the gridline, so you can go with the first part of this answer. I've left the rest in here in case someone else wants a more dynamic solution. Note that you could also just use the max value without padding if you wanted to set it explicitly to a value higher than the gridline.
As of this writing, there actually is a way to reset the y-max to be dynamic, after setting it to specific max. You do so by setting max to undefined, like so: chart.axis.max(undefined);.
Here, have a working jsfiddle.

flot is it possible to set just the begining of the x axis?

I am working on flot jquery library, and I used to use this code in order to tell flot to inference the x-axis itself
xaxis: {
},
now i have a case in which I need to show the values starting from zero in x-axis, i don't care about last value, so I need flot to calculate it dinamically. it is possible to set just the begining ?
what I tried
I couldn't find such an option using google so I calculated the max value my self and I set the x-axis manually between zero and that max value. that approaches works in some cases, but i do need to handle all the senarios so i thought let me ask here first to see if there is a built-in option for that
You can set the minimum or maximum extent of the axes like this:
xaxis: {min: 0, max: 999}
See https://github.com/flot/flot/blob/master/API.md#customizing-the-axes

Highcharts - Issue with negative values when displaying multiple axes

We're attempting to display two series of data on the same chart. The first series (ie: number of quotations) can only contain positive integers (and 0). The second series (ie: sales value) can contain both positive and negative float values (in case you're wondering, the negative values result from the issuing of credit notes).
As indicated on the attached image, the problem we're having is that when the second series contains negative values, the 0-point "base line" of the two series of data is no longer shared.
We've tried setting the "min" options of the Y axes to 0, but then we lose out the insight on negative values.
We've also tried setting the min of the first series to be equal to the minimum extreme of the second series, but unfortunately this doesn't scale the columns very nicely (since the values of each Y axis are on completely different scales, ie: 10s vs 1000s).
How can we configure the chart so that the 0-point "base line" is shared? In other words, how would we make the blue columns start at the same base line as the green 0 point?
Update
Linger's answer is a step in the right direction. Setting the min and tickinterval for both axes does the trick. However the values need to be determined dynamically based on variable data, which is where I am now stuck.
Any tips on how these min and tickinterval values can be determined before I generate the chart?
I've done some thinking about it in the mean time. The values associated with the left axis (blue / quotations) are always positive and start from zero. Thus it is the right axis (green / sales) that dictates the number of ticks to show below the zero point. Now since highcharts automatically determines the best scale for both blue and green, all I need to do is find a way to set the left axis' minimum value like so (excuse the pseudo-code):
var factor = right_axis.min / right_axis.tickinterval;
left_axis.min = factor * left.tickinterval;
Note: I have seen the reference API has a setExtremes() method under Axis, but this would require me to first initialise the chart, and then go back and update its left axis. I am hoping to do this before drawing the chart. Perhaps I'm overlooking something obvious?
Thanks.
You can control what you are asking for with a combination of tickInterval and min on the yaxis as demonstrated in this jsfiddle mock up.
EDIT
In your code while reading in the XML you will have to keep track of what the lowest value is and also the highest value on the sales side. Then decide how you want to display those values if they meet a certain value. After that use if statements to set the values. Here is a couple of examples.
Low less than -50 and greater -90
With High less than 400
Primary Axis: min: -2, tickInterval: 1,
Secondary Axis: min: -100, tickInterval: 50
Example
Low less than -50 and greater -90
With High greater than 400
Primary Axis: min: -1, tickInterval: 1,
Secondary Axis: min: min: -100, tickInterval: 100,
Example
To figure out what the min on the Primary Axis should be you simply divide the min on the Secondary Axis by its tickInterval. Then the tickInterval for the Primary Axis would always be 1.
You can also calculate second axis tick positions based on the max series value related to this axis and the first axis ticks positions to get the same amount of ticks and 0 line shared.
Using axis.update() method update tick positions in the second axis using property tickPositions.
Example with a load event. Notice, that when you add points dynamically you have to make those calculations and update tick positions each time your first axis ticks will change:
chart: {
type: 'column',
events: {
load: function() {
var chart = this,
yAxis = this.yAxis,
max = yAxis[1].dataMax,
positiveTicksAmount = 0,
negativeTicksAmount = 0,
tickPositions = [],
tickInterval,
min,
i;
yAxis[0].tickPositions.forEach(function(tick) {
if (tick > 0) {
positiveTicksAmount++;
} else if (tick < 0) {
negativeTicksAmount++;
}
});
tickInterval = max / positiveTicksAmount;
for (i = negativeTicksAmount; i > 0; i--) {
tickPositions.push(-tickInterval * i);
}
for (i = 0; i <= positiveTicksAmount; i++) {
tickPositions.push(
tickInterval * i
);
}
yAxis[1].update({
tickPositions: tickPositions
});
}
}
},
Jsfiddle examples:
https://jsfiddle.net/wchmiel/84q0sxrt/
http://jsfiddle.net/wchmiel/nuj7fagh/
Api reference:
https://api.highcharts.com/class-reference/Highcharts.Axis#update
https://api.highcharts.com/highcharts/yAxis.tickPositions

What the right way to graph negative numbers in Protovis?

For the simplest use case, a bar chart with values ranging from -10 to 10, how does one go about coding this cleanly using the Protovis JavaScript charting library?
By cleanly I mean centering the axis, showing x and y axis labels, and representing the column values of the chart where negative values fall below the y axis and positive values exceed the y axis.
Here's a working example: http://jsfiddle.net/nrabinowitz/yk5By/3/
The important parts of this are as follows:
Make an x-axis scale going from your min value to your max value (in your case, it would be pv.Scale.linear(-10,10).range(0,w); in my example, I calculate min and max based on the data).
Base the width of the bar on the absolute distance of the datum from 0:
.width(function(d) { return Math.abs(x(d) - x(0)); })
Then adjust the .left() property based on whether the datum is positive or negative:
.left(function(d) { return d > 0 ? x(0) : x(0) - this.width(); });
Because we're using a simple x-axis scale, the adding axis labels is super-easy:
vis.add(pv.Label)
.data(x.ticks()) // you could also use pv.range(min, max, 1) here
.left(x);

Categories