Highcharts yAxis.max manage tick intervals dynamically - javascript

I'm trying to set the max and min of y value dynamically based on the data but it is having some troubles for some values. I think the highchart couldn't set values that doesn't have a proper tick.
For eg: min: 3 and max 10. Then, the highchart won't set these values instead of that it will set a value ranging from 0...14. This is just an example value, sometimes I get 36000.14 as min and 454533.18 as max.
So my logic isn't working in that case.
This is the part of code which I currently have:
data = [3.43, 3.58, 4.86, 8.55, 8.77, 4.44, 9.67]
maximum_val = Math.ceil(maximum_val) eg: 10
minimum_val = Math.floor(minimum_val) eg: 3
evolution_options.yAxis[$('#div_count_'+div).find('#y_axis_lbl').text()] = {
min: minimum_val,
max: maximum_val,
title: false,
labels: {
style: {
color: 'black'
}
}
}
Update
Fiddle : http://jsfiddle.net/e3fy1vu9/
Further Brainstorming
I think it is because the min value isn't a multiple of the max value so Highchart couldn't calculate how to split the tick. If there was any way so I could set the max value as the multiple of the min value.

Here is my advice how to calculate the max and min for yAxis from the defined data.
Demo: https://jsfiddle.net/BlackLabel/0qwt1kx7/
yAxis: {
min: Math.floor(Math.min(...data)),
max: Math.round(Math.max(...data)),
tickAmount: Math.round(Math.max(...data)) - Math.floor(Math.min(...data)) + 1 //1 count the min or max as itself
},
Please test it and let me know if it fits to your requirements. Because the tickAmount value depends on how many values is included in the data array and probably some modifications are needed for larger data.
EDIT:
Try to use this custom solution to calculate the yAxis positions:
Demo: http://jsfiddle.net/BlackLabel/ztaj6Lkd/
var positions = [],
tickNumbers = 5,
tick = Math.floor(Math.min(...data));
for(let i = 0; i < tickNumbers; i++) {
positions.push((Math.round(tick * 100) / 100));
tick += Math.round(Math.max(...data)) / tickNumbers
}
//add the max
positions.push(Math.round(Math.max(...data)))

Hi I have fixed it by setting this alignTicks:false option.
evolution_options.yAxis[$('#div_count_'+div).find('#y_axis_lbl').text()] = {
min: minimum_val,
max: maximum_val,
title: false,
labels: {
style: {
color: 'black'
}
},
alignTicks: false
}

Related

How to make yAxis column start with value min yAxis in Highcharts?

I use Highcharts to plot the graph, but there is a problem I am facing. data contains the values from 1 to n. So I want the yAxis column to start at 1. I set yAxis min = 1 but it doesn't fix my problem.
Here is a jsfiddle that illustrates the problem I am having:
Link
yAxis: {
title: null,
endOnTick: false,
min: 1
}
Is there any way to solve my problem? I expect it like this:
I expect it like this
The simplest solution is to use tickPositioner function and modify the first tick. For example:
yAxis: {
title: null,
tickPositioner: function() {
const tickPositions = [...this.tickPositions];
tickPositions[0] = 1;
return tickPositions;
},
endOnTick: false,
startOnTick: false,
min: 1
}
Live demo: https://jsfiddle.net/BlackLabel/rf3cm8Lw/
API Reference: https://api.highcharts.com/highcharts/xAxis.tickPositioner
Thanks for ppotaczek answer. I find it pretty cool, can ignore blanks, starting from the smallest element. I have a solution for this and am posting it here for anyone who needs it.
tickPositioner: function () {
var positions = [],
tick = Math.floor(this.dataMin),
increment = Math.ceil((this.dataMax - this.dataMin) / 6);
if (this.dataMax !== null && this.dataMin !== null) {
for (tick; tick - increment <= this.dataMax; tick += increment) {
positions.push(tick);
}
}
return positions;
}

How to access the value of a custom attribute in data from highcharts

I have this in my code
series: [{
name: 'Velocidad',
turboThreshold: 5000,
data: (function() {
// generate an array of random data
var data = [],
i;
for (i = 0; i < valor; i++) {
data.push({
x: dataUtc[i],
y: dataVel[i],
id: i
});
}
return data;
})(),
tooltip: {
valueDecimals: 0,
valueSuffix: 'Kms/H'
}
}]
When I try to get the maximum value I only get the x or y value.
I need to get the id value though.
What can I do?
I tried the following:
var chart = $('#containerVelocidad').highcharts();
min = chart.xAxis[0].min;
max = chart.xAxis[0].max;
Unfortunately that didn't help.
First of all, use yAxis.dataMax not yAxis.max. The second one is returning actual extremes, when sometimes you may have different extremes, than just from one series (zooming, setting extremes, multiple series etc.).
Demo: http://jsfiddle.net/ez4hjazk/1/
And code:
var max = chart.yAxis[0].dataMax,
maxIndex = chart.series[0].yData.indexOf(max), //get index from yData, read more about .indexOf() !
data = chart.series[0].data;
// make sure point is within actual extremes
if(maxIndex > -1) {
console.log("max = " + max, 'id = ' + data[maxIndex].id);
}
Do you need to get the maximum/minimum of id?
If so, try chart.series[0].data[i].id. Here's an example: http://jsfiddle.net/ez4hjazk/

Long array of small data points is rendered as a jagged line

The Goal
I'm attempting to render a long series of data (around 200 ticks, from small float values like 1.3223) into a line chart.
The Issue
When I use a series of data that changes only a small amount (around 0.0001 every tick), the chart is rendered as very jagged (scissor like). I would like to somehow fix it to have a "saner" radius between each point on the graph.
A Good Example
On the other hand, when rendering higher values (around 1382.21) with bigger difference between ticks (from 0.01 to 0.05 +/-) the graph is rendered more smooth and aesthetically pleasing.
Edit: As user Arie Shaw pointed out, the actual low or high values don't make a difference and it remains an issue of representing small "monotonous" changes is a less jagged form.
The Code
var initChart = function(data, container) {
new Highcharts.Chart({
chart: {
type: "area",
renderTo: container,
zoomType: 'x'
},
title: {
text: ''
},
xAxis: {
labels: {
enabled: false
}
},
yAxis: {
title: {
text: ''
}
},
legend: {
enabled: false
},
color: '#A3D8FF',
plotOptions: {
area: {
fillColor: '#C6E5F4',
lineWidth: 1,
marker: {
enabled: false
},
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
threshold: null
}
},
exporting: {
enabled: false
},
series: [{
name: "TEST",
data: data
}]
});
};
Both graphs, and sample data sets are presented in the following fiddle:
http://jsfiddle.net/YKbxy/2/
The problem you're experiencing is unavoidable: If you have a lot of small variations over time, the graph is going to appear jagged provided that you show each data point.
The key point is that last phrase.
One way to 'smooth out' the rough parts would be to average the data. For example:
var myData = []; //... Some array of data; assuming just numbers
var averageData = function (data, factor) {
var i, j, results = [], sum = 0, length = data.length, avgWindow;
if (!factor || factor <= 0) {
factor = 1;
}
// Create a sliding window of averages
for(i = 0; i < length; i+= factor) {
// Slice from i to factor
avgWindow = data.slice(i, i+factor);
for (j = 0; j < avgWindow.length; j++) {
sum += avgWindow[j];
}
results.push(sum / avgWindow.length)
sum = 0;
}
return results;
};
var var initChart = function(data, container) {
new Highcharts.Chart({
series: [{
name: "TEST",
data: averageData(myData, 2)
}]
});
});
This method also has the advantage that you could (potentially) reuse the function to compare the averaged data to the regular data, or even toggle between how much to average the data.
You can always use areaspline instead of area, see: http://jsfiddle.net/YKbxy/3/
why dont you treat you .00001 data as 1, so times 10000, and then write it in your legend like that.
You should even do that as a test, since if the chart looks fine then, it means there is a problem in the dataset numbers when you return it to normal, since high charts takes the difference between high and low...
Either you must approximate your data by only using a few decimal places or you must average out the values using something like:
var data = new Array(200);
var smallArray = new Array(5);
var averagedData = new Array(20);
for (var index=0; index<=averagedData.length; index++){
for(var i = 0; i<=smallArray.length; i++){
smallArray[i] = data[i + index * 5];
}
averagedData[index] = (smallArray[1] + smallArray[2] + smallArray[3] + smallArray[4] + smallArray[5])/smallArray.length;
}
Then you will only need to plot 20 averaged points on an array of 200 data points. You can change the values for what you need.
In the end the issue is in the frequency of the points or their plotting on yAxis.
When I provide more realistic positioning (e.g timestamp) it will look good.
Meaning that jaggedness is a result of the small changes over constant yAxis progression, which is most similar to nt3rp's answer

jqPlot points not correct when numberTicks set

I'm trying to limit the number of ticks on a dynamic jqplot I'm setting up. Unfortunately, when I do it, the points do not look accurate. Here's what it looks like:
As you can see, the point on 10/05/12, for example, is not on it's correct axis. I realize that now these points are estimated, but the points must look accurate on the graph -- especially when hovering over the points gives you their correct date and y-axis value.
Here's my code for this intilization, if that helps:
var datepickerBegin = $("#datepicker_start").datepicker({dateFormat: "dd/mm/yyyy"}).val();
var datepickerEnd = $("#datepicker_to").datepicker({dateFormat: "dd/mm/yyyy"}).val();
var startDiff = $("#datepicker_start").datepicker("getDate");
var endDiff = $("#datepicker_to").datepicker("getDate");
alert(startDiff)
alert(endDiff)
// Check if dates are more than a week apart
if(endDiff - startDiff >= 15 * 86400 * 1000) {
var plot2 = $.jqplot('chart2', jsonurl,{
title: "Storage Space",
dataRenderer: ajaxDataRenderer,
dataRendererOptions: {unusedOptionalUrl: jsonurl},
axes: {
xaxis: {
'numberTicks' : 15,
min: datepickerBegin,
max: datepickerEnd,
renderer:$.jqplot.DateAxisRenderer,
rendererOptions:{tickRenderer:$.jqplot.CanvasAxisTickRenderer},
tickInterval: '1 day',
tickOptions:{formatString:'%#m/%#d/%Y'
}
},
yaxis: {
label: "MB",
tickOptions:{formatString:'%d '},
min: 0
}
},
highlighter: {
show: true,
sizeAdjust: 7.5
}
});
// Somehow fix the line?
plot2.redraw({});
}
Anyone out there have a fix for this? Thanks!

how to display y-axis value to integers only in jqplot

How do i make the value of y-axis into integer?
i currently have this value 0.0 1.0 1.5 2.0 2.5 3.0. i want to change it to some thing like this 0 1 2 3 etc....
thank you! cheers!
if i understand what you want, is to display in y axis integer values.
Try this,
axesDefaults:
{
min: 0,
tickInterval: 1,
tickOptions: {
formatString: '%d'
}
}
Override createTicks function and introduce new axis bool property - integersOnly.
// jqplot adding integersOnly option for an axis
var oldCreateTicks = $.jqplot.LinearAxisRenderer.prototype.createTicks;
$.jqplot.LinearAxisRenderer.prototype.createTicks = function (plot) {
if (this.integersOnly == true) {
var db = this._dataBounds;
var min = ((this.min != null) ? this.min : db.min);
var max = ((this.max != null) ? this.max : db.max);
var range = max - min;
if (range < 3) {
if (this.min == null) {
this.min = 0;
}
this.tickInterval = 1;
}
}
return oldCreateTicks.apply(this, plot);
}
Just to build on the top answer.
axes: {
yaxis: {
min: 0,
tickInterval: 1,
tickOptions: {
formatString: '%d'
}
}
}
Would just apply this to the yaxis. Helpful, if you have a bar chart or some other chart and you want to isolate the axis.
Try parseInt(y_axis)
(filler text, answer too short)

Categories

Resources