How to start lines on columns in HighCharts - javascript

I have a combnined chart with groups of columns and lines. Each column corresponds to a line. I want each line to start on their respective column. Here is an example:
http://jsfiddle.net/aozdjab2/1/
Now, The number of columns is variable, so I want to calculate the pointPlacement for the lines dynamically.
What is the best way to do this? Is there a way to tell the lines to start at the columns?
If not, how do I calculate the point placements? The number of lines and columns will vary, as well as the number of groups on the x-axis.
Thanks.
Because SO requires code:
{
type: 'line',
name: 'Jane-line',
data: [3, 2, 1, 3, 4],
pointPlacement: -0.2
},
{
type: 'line',
name: 'john-line',
data: [2, 3, 5, 7, 6],
pointPlacement: 0
},
{
type: 'line',
name: 'joe-line',
data: [4, 3, 3, 9, 0],
pointPlacement: 0.2
}

You can add new xAxis that will be related to you line series. This series will have more categories, so ticks will be thicker than in your normal axis.
You can check, if line series has related visible column series in your chart and if yes, you can add this series to your chart.
Here you can find custom function I wrote for this case:
var positioningLineSeries = function(chart, event) {
if (redraw) {
var columnSeries = [],
each = Highcharts.each,
numberOfColumnSeries = 0,
categoriesFor2Axis = [],
i;
each(chart.series, function(s) {
if (s.type === 'column' && s.visible) {
columnSeries.push(s);
}
});
for (i = 0; i < chart.series.length; i++) {
if (chart.series[i].type === 'line') {
chart.series[i].remove(false);
i--;
}
}
numberOfColumnSeries = columnSeries.length;
redraw = false;
each(chart.xAxis[0].categories, function(c) {
for (i = 0; i < numberOfColumnSeries + 2; i++) {
categoriesFor2Axis.push(c);
}
});
chart.xAxis[1].update({
categories: categoriesFor2Axis,
min: 0,
max: categoriesFor2Axis.length - 1
}, false);
var newData, newLineSeries = $.extend(true, [], lineSeries);
each(newLineSeries, function(s) {
newData = [];
each(columnSeries, function(cS, i) {
if (cS.options.ID === s.columnID) {
each(s.data, function(p, j) {
newData.push([p[0] + i + 1 + j * (numberOfColumnSeries + 1), p[1]]);
});
s.data = newData;
chart.addSeries(s, false);
}
});
});
chart.redraw();
} else {
redraw = true;
}
};
And here you can find an example how it can work: http://jsfiddle.net/aozdjab2/6/

Related

HightCharts Renko chart disapear after zoom

I used this example in the HightCharts library to make a Renko chart, Everything works fine with this example. But when I use my own data to show a chart It works fine but when I zoom the chart it disappears. I don't know what the problem the data is the same as the example.
The example with my data
https://jsfiddle.net/aypx6nfo/
Before zoom.
After zoom
MY CODES
function linearDataToRenko(data, change) {
var renkoData = [],
prevPrice = data[0][1],
prevTrend = 0, // 0 - no trend, 1 - uptrend, 2 - downtrend
length = data.length,
i = 1;
for (; i < length; i++) {
if (data[i][1] - data[i - 1][1] > change) {
// Up trend
if (prevTrend === 2) {
prevPrice += change;
}
renkoData.push({
x: data[i][0],
y: prevPrice,
low: prevPrice,
high: prevPrice + change
});
prevPrice += change;
prevTrend = 1;
} else if (Math.abs(data[i][1] - data[i - 1][1]) > change) {
if (prevTrend === 1) {
prevPrice -= change;
}
// Down trend
renkoData.push({
x: data[i][0],
y: prevPrice,
low: prevPrice - change,
high: prevPrice,
color: 'black'
});
prevPrice -= change;
prevTrend = 2;
}
}
return renkoData;
}
$.getJSON(`https://api.twelvedata.com/time_series?symbol=AAPL&interval=1day&apikey=MY-API-KEY&outputsize=500`, function(data) {
let tempData = [];
for (var i = 0; i < data.values.length; i++) {
tempData.push([
new Date(data.values[i].datetime),
parseFloat(data.values[i].volume),
]);
}
// Create the chart
Highcharts.stockChart('container', {
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Stock Price'
},
series: [{
name: 'AAPL',
type: 'columnrange',
fillColor: 'transparent',
turboThreshold: 0,
groupPadding: 0,
pointPadding: 0,
borderWidth: 1,
data: linearDataToRenko(tempData, 1),
dataGrouping: {
enabled: false
},
tooltip: {
valueDecimals: 2
}
}]
});
});
You need to use timestamps in milliseconds as x values and sort your data.
let tempData = [];
for (var i = 0; i < data.values.length; i++) {
tempData.push([
new Date(data.values[i].datetime).getTime(),
parseFloat(data.values[i].volume),
]);
}
tempData.reverse();
Live demo: https://jsfiddle.net/BlackLabel/f8sex6zj/
API Reference: https://api.highcharts.com/highstock/series.columnrange.data

Maximum values series in Highcharts

I'm struggling with the problem of showing additional serie that will contains maximum values for every x. Like this:
I was able to parse all series to aggregate points and also found cross points to include them. Currently I have a problem with cross point (A) that are below one of the series. (Solution A in fiddle)I was thinking about calculating line and check if the point A belongs to that line. This will fix scenario but will cause problem for point B bc it doesn't belong to calculated line but should be included in serie.
Could any one point me to the right direction?
var chart = Highcharts.chart('container', {
chart: {
type: 'area',
zoomType: 'x',
backgroundColor:null,
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
month: '%b %e',
year: '%b'
},
},
plotOptions: {
series: {
fillOpacity: 0.1,
marker: {
enabled: false
}
}
}
});
chart.addSeries({"id":0,"connectNulls":true,"data":[[1524469020000,30],[1524469080000,30],[1524469140000,30],[1524469200000,30],[1524469260000,30],[1524469320000,30],[1524469380000,30],[1524469440000,30],[1524469500000,30],[1524469560000,58],[1524469620000,4],[1524469680000,4],[1524469740000,4],[1524469800000,4],[1524469860000,4],[1524469920000,4],[1524469980000,4],[1524470040000,4],[1524470100000,4],[1524470160000,4],[1524470220000,4],[1524470280000,4],[1524470340000,4],[1524470400000,4],[1524470460000,4],[1524470520000,22],[1524470580000,22],[1524470640000,22],[1524470700000,22]],"name":"Serie A","color":"#30e430","yAxis":0});
chart.addSeries({"id":1,"connectNulls":true,"data":[[1524469020000,35],[1524469080000,35],[1524469140000,35],[1524469200000,35],[1524469260000,35],[1524469320000,35],[1524469380000,35],[1524469440000,35],[1524469500000,35],[1524469560000,25],[1524469620000,25],[1524469680000,25],[1524469740000,25],[1524469800000,25],[1524469860000,25],[1524469920000,25],[1524469980000,59],[1524470040000,59],[1524470100000,59],[1524470160000,59],[1524470220000,59],[1524470280000,59],[1524470340000,59],[1524470400000,59],[1524470460000,59],[1524470520000,59],[1524470580000,59],[1524470640000,59],[1524470700000,59]],"name":"Serie B","color":"#0cb5ed","yAxis":0});
chart.addSeries({"id":2,"connectNulls":true,"data":[[1524469020000,18],[1524469080000,18],[1524469140000,18],[1524469200000,18],[1524469260000,18],[1524469320000,18],[1524469380000,18],[1524469440000,18],[1524469500000,18],[1524469560000,18],[1524469620000,18],[1524469680000,18],[1524469740000,18],[1524469800000,18],[1524469860000,18],[1524469920000,18],[1524469980000,18],[1524470040000,18],[1524470100000,18],[1524470160000,18],[1524470220000,18],[1524470280000,18],[1524470340000,18],[1524470400000,18],[1524470460000,18],[1524470520000,18],[1524470580000,18],[1524470640000,18],[1524470700000,18]],"name":"Serie C","color":"#e8ad23","yAxis":0});
$('#button').click(function () {
var results = getChartPointValues();
var data = prepareSummarySeries(results);
//clean previously added virutal series
for(var i in chart.series){
var serie = chart.series[i];
if(serie.userOptions.is_virtual == true)
serie.remove();
}
chart.addSeries({
id: 'virtual_max_b',
is_virtual: true,
'connectNulls': true,
'data' : data.max_b,
'name' : 'Solution A',
'color' : '#000',
'yAxis': 0,
});
chart.addSeries({
id: 'virtual_max_a',
is_virtual: true,
'connectNulls': true,
'data' : data.max_a,
'name' : 'Base Solution',
'color' : '#ff0000',
'yAxis': 0,
});
});
/*
* Calculate max values for every point
*/
var prepareSummarySeries = function(data){
var tmp_keys = Object.keys(data); ///sort
tmp_keys = tmp_keys.sort();
var counter = tmp_keys.length;
var results = {
'max_a': [],
'max_b': [],
};
for(var k = 0; k < counter; k++){
var key = tmp_keys[k];
var x_pos = parseFloat(key);
if(x_pos % 1 !== 0)
{
var prev_point = results.max_b.slice(-1)[0];
var current_point = [x_pos, data[key][0]];
var next_point = [ parseFloat(tmp_keys[k+1]), Math.max.apply(null, data[tmp_keys[k+1]] )];
if( checkIfPointBelongsToChart(prev_point, current_point, next_point) ){
results.max_b.push([ x_pos, current_point[1] ]);
}
} else {
results.max_b.push([ x_pos, Math.max.apply(null, data[key]) ]);
}
results.max_a.push([ x_pos, Math.max.apply(null, data[key]) ]);
}
return results;
};
var get_line_intersection = function(p0,p1,p2,p3){
var p0_x = p0.x;
var p0_y = p0.y;
var p1_x = p1.x;
var p1_y = p1.y;
var p2_x = p2.x;
var p2_y = p2.y;
var p3_x = p3.x;
var p3_y = p3.y;
var s1_x, s1_y, s2_x, s2_y;
s1_x = p1_x - p0_x; s1_y = p1_y - p0_y;
s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
var s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
var t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
return [p0_x + (t * s1_x),p0_y + (t * s1_y)];
}
return false;
};
var checkIfPointBelongsToChart = function(prev_point, current_point, next_point)
{
var slope = (next_point[1] - prev_point[1]) / (next_point[0] - prev_point[0]);
var b = prev_point[1] - slope * prev_point[0];
var tmp_y = slope * current_point[0] + b;
return (tmp_y == current_point[1])? true : false;
};
// create array with every x point with every possible y value
// im not taking only max here bc later we could need min instead of max
var getChartPointValues = function(){
var results = {}
var self = this;
var points = [];
var checked_series = [];
for(var k =0; k < chart.series.length; k++)
{
var entry = chart.series[k];
if(entry.userOptions.is_virtual == true || entry.visible == false)
continue;
var s1_points = entry.data;
var c1 = s1_points.length;
//add all points from serie
for(var i = 0; i < c1; i++)
{
if(s1_points[i] == undefined || !s1_points[i].isInside)
continue;
if(points[s1_points[i].x] == undefined){
points[s1_points[i].x] = [];
}
points[s1_points[i].x].push(s1_points[i].y);
}
//check all points in all charts for crossing points
for(var s in chart.series){
var serie = chart.series[s];
if(serie.userOptions.is_virtual == true || serie.visible == false)
continue;
//skip serie if combination of series was already checked
var current_check = entry.userOptions.id + '_' + serie.userOptions.id;
if(checked_series.indexOf(current_check) != -1 || serie.userOptions.is_virtual == true)
continue;
checked_series.push(current_check);
checked_series.push(serie.userOptions.id + '_' + entry.userOptions.id);
if(serie.index != entry.index){
var s2_points = serie.data;
var c2 = s2_points.length;
for(var i = 0; i < c1; i++)
{
if(s1_points[i] == undefined || !s1_points[i].isInside)
continue;
for(var j = 0; j < c2; j++)
{
if(s2_points[j] == undefined || !s2_points[j].isInside)
continue;
var cross = [];
if(s1_points[i-1] != undefined && s2_points[j-1] != undefined){
if(cross = get_line_intersection(s1_points[i-1], s1_points[i], s2_points[j-1], s2_points[j])){
if(points[cross[0]] == undefined){
points[cross[0]] = [];
}
points[cross[0]].push(cross[1])
}
}
}
}
}
};
};
return points;
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<button id="button">Add Maximum series</button>
<div id="container" style="height: 400px"></div>
jsFiddle
I have tried to solve this using a slightly different method. The gist of it is:
Find the series that has the max point
Find the series that has the next max point
Check if there is an intersect between the lines of these two series
If there is an intersect, add that as a separate point
Add the next max point
There is one caveat with doing it like this, a sparse series has the ability to ruin the graph, like this: https://jsfiddle.net/ewolden/3koe86sx/15/
Solving that issue would be tedious, requiring you to find all x points, and for lines without all points present, fill in their values.
That being said, as long as the series have roughly the same number of points, this should work well.
var get_line_intersection = function(p0, p1, p2, p3) {
var p0_x = p0.x;
var p0_y = p0.y;
var p1_x = p1.x;
var p1_y = p1.y;
var p2_x = p2.x;
var p2_y = p2.y;
var p3_x = p3.x;
var p3_y = p3.y;
var s1_x, s1_y, s2_x, s2_y;
s1_x = p1_x - p0_x;
s1_y = p1_y - p0_y;
s2_x = p3_x - p2_x;
s2_y = p3_y - p2_y;
var s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
var t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
return [p0_x + (t * s1_x), p0_y + (t * s1_y)];
}
return false;
};
//Gets the next point
function getNextPoint(series, current_x, current_y) {
nextPoint = {
next_x: 0,
next_y: 0,
x: 0,
y: -1,
prev_x: 0,
prev_y: 0
}
for (var i = 0; i < series.length; i++) {
for (var j = 1; j < series[i].length; j++) {
if (series[i][j].x > current_x) { //Goes one step past current timestamp
if (series[i][j].y > nextPoint.y || nextPoint.y == -1) { //Checks that this is the max number, could be changed to find min as well
if (j < series[i].length - 1) { //Checks if this is the last point (to avoid going past last index)
nextPoint = {
next_x: series[i][j + 1].x,
next_y: series[i][j + 1].y,
x: series[i][j].x,
y: series[i][j].y,
prev_x: series[i][j - 1].x,
prev_y: series[i][j - 1].y,
}
} else {
nextPoint = {
x: series[i][j].x,
y: series[i][j].y,
prev_x: series[i][j - 1].x,
prev_y: series[i][j - 1].y,
}
}
}
break;
}
}
}
return nextPoint
}
function getAllSeries(chart) {
var allSeries = []
for (var i = 0; i < chart.series.length; i++) {
allSeries.push(chart.series[i].data)
}
return allSeries
}
var chart = Highcharts.chart('container', {
chart: {
type: 'area',
zoomType: 'x',
backgroundColor: null,
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
month: '%b %e',
year: '%b'
},
},
plotOptions: {
series: {
fillOpacity: 0.1,
marker: {
enabled: false
}
}
}
});
chart.addSeries({
"id": 0,
"connectNulls": true,
"data": [
[1524469020000, 30],
[1524469080000, 30],
[1524469140000, 30],
[1524469200000, 30],
[1524469260000, 30],
[1524469320000, 30],
[1524469380000, 30],
[1524469440000, 30],
[1524469500000, 30],
[1524469560000, 58],
[1524469620000, 4],
[1524469680000, 4],
[1524469740000, 4],
[1524469800000, 4],
[1524469860000, 4],
[1524469920000, 4],
[1524469980000, 4],
[1524470040000, 4],
[1524470100000, 4],
[1524470160000, 4],
[1524470220000, 4],
[1524470280000, 4],
[1524470340000, 4],
[1524470400000, 4],
[1524470460000, 4],
[1524470520000, 22],
[1524470580000, 22],
[1524470640000, 22],
[1524470700000, 22]
],
"name": "Serie A",
"color": "#30e430",
"yAxis": 0
});
chart.addSeries({
"id": 1,
"connectNulls": true,
"data": [
[1524469020000, 35],
[1524469080000, 35],
[1524469140000, 35],
[1524469200000, 35],
[1524469260000, 35],
[1524469320000, 35],
[1524469380000, 35],
[1524469440000, 35],
[1524469500000, 35],
[1524469560000, 25],
[1524469620000, 25],
[1524469680000, 25],
[1524469740000, 25],
[1524469800000, 25],
[1524469860000, 25],
[1524469920000, 25],
[1524469980000, 59],
[1524470040000, 59],
[1524470100000, 59],
[1524470160000, 59],
[1524470220000, 59],
[1524470280000, 59],
[1524470340000, 59],
[1524470400000, 59],
[1524470460000, 59],
[1524470520000, 59],
[1524470580000, 59],
[1524470640000, 59],
[1524470700000, 59]
],
"name": "Serie B",
"color": "#0cb5ed",
"yAxis": 0
});
chart.addSeries({
"id": 2,
"connectNulls": true,
"data": [
[1524469020000, 18],
[1524469080000, 18],
[1524469140000, 18],
[1524469200000, 18],
[1524469260000, 18],
[1524469320000, 18],
[1524469380000, 18],
[1524469440000, 18],
[1524469500000, 18],
[1524469560000, 18],
[1524469620000, 18],
[1524469680000, 18],
[1524469740000, 18],
[1524469800000, 18],
[1524469860000, 18],
[1524469920000, 18],
[1524469980000, 18],
[1524470040000, 18],
[1524470100000, 18],
[1524470130000, 80],
[1524470160000, 18],
[1524470220000, 18],
[1524470280000, 18],
[1524470340000, 18],
[1524470400000, 18],
[1524470460000, 18],
[1524470520000, 18],
[1524470580000, 18],
[1524470640000, 18],
[1524470700000, 18]
],
"name": "Serie C",
"color": "#e8ad23",
"yAxis": 0
});
$('#button').click(function() {
series = getAllSeries(chart)
var currentPoint = {
next_x: 0,
next_y: 0,
x: -1,
y: 0,
prev_x: 0,
prev_y: 0
}
var max_x = 0;
//finds the first point
for (var i = 0; i < series.length; i++) {
if (currentPoint.y < series[i][0].y || currentPoint.x == -1) { //makes sure this is the largest point
currentPoint = {
prev_x: series[i][0].x,
prev_y: series[i][0].y,
x: series[i][0].x,
y: series[i][0].y,
next_x: series[i][1].x,
next_y: series[i][1].y
}
}
if (max_x < series[i][series[i].length - 1].x) {
max_x = series[i][series[i].length - 1].x;
}
}
result = []
result.push({ //since the first point comes from the above code, we need to add it explicitly
x: currentPoint.x,
y: currentPoint.y
})
while (currentPoint.x != max_x) { //loop through all points
nextPoint = getNextPoint(series, currentPoint.x, currentPoint.y);
let intersect = get_line_intersection({
x: nextPoint.prev_x,
y: nextPoint.prev_y
}, {
x: nextPoint.x,
y: nextPoint.y
}, {
x: currentPoint.x,
y: currentPoint.y
}, {
x: currentPoint.next_x,
y: currentPoint.next_y
})
if (intersect != false) { //if there is an intersect point, make sure to add it
result.push({
x: intersect[0],
y: intersect[1]
})
}
result.push({
x: nextPoint.x,
y: nextPoint.y
});
currentPoint = nextPoint
}
chart.addSeries({
name: 'Max Points',
lineColor: 'red',
//dashStyle: 'LongDash',
data: result
})
})
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<button id="button">Add Maximum series</button>
<div id="container" style="height: 400px"></div>
jsfiddle example: https://jsfiddle.net/ewolden/3koe86sx/14/

Draw a line on Google Charts ScatterChart

I have a ScatterChart where I need to draw a diagonal line (of the function y=x) that serves as a visual aid. Is it possible ? if so, how can I do it?
you can use a ComboChart to display both scatter and line series'
and a DataView to provide the function for y=x
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages:['corechart']
});
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'x');
data.addColumn('number', 'y0');
data.addRows([
[1, 37.8],
[2, 30.9],
[3, 25.4],
[4, 11.7],
[5, 11.9],
[6, 8.8],
[7, 7.6],
[8, 12.3],
[9, 16.9],
[10, 12.8],
[11, 5.3],
[12, 6.6],
[13, 4.8],
[14, 4.2]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
label: 'y1=x',
type: 'number',
calc: function (dt, row) {
return dt.getValue(row, 0)
}
}]);
var options = {
seriesType: 'scatter',
series: {
1: {
type: 'line'
}
}
};
var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
chart.draw(view, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Another solution is that you can use Scatter chart with multi-series, and set lineWidth = 1 and pointSize = 0 for Line charts!
See the following example:
function main() {
const xMin = -2 * Math.PI;
const xMax = 2 * Math.PI;
const f1 = x => Math.cos(x) + Math.random();
const f2 = x => Math.cos(x);
const x = linspace(xMin, xMax, 20);
const y1 = x.map(f1);
const y2 = x.map(f2);
scatterLineChart(document.getElementById('scatter-line-chart'), x, [y1, y2], 'Scatter: Cos(x) + Noise, Line: Cos(x)', 'x', ['Cos(x) + Noise', 'Cos(x)']);
}
function linspace(a, b, n = 100) {
const data = new Array(n);
const d = (b - a) / (n - 1);
data[0] = a;
data[n - 1] = b;
n = n - 1;
for (let i = 1; i < n; i++) {
data[i] = data[i - 1] + d;
}
return data;
}
function createSeriesDataTable(x, ys, xLabel, yLabels) {
// data
const data = new google.visualization.DataTable();
// - columns
data.addColumn('number', xLabel);
yLabels.forEach(yLabel => {
data.addColumn('number', yLabel);
});
// - rows
const n = x.length;
const m = ys.length;
const rows = Array(n);
for (let i = 0; i < n; i++) {
rows[i] = Array(1 + m);
rows[i][0] = x[i];
for (let j = 0; j < m; j++) {
rows[i][j + 1] = ys[j][i];
}
}
data.addRows(rows);
// return
return data;
}
function scatterLineChart(parentElement, x, ys, title, xLabel, yLabels) {
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
const data = createSeriesDataTable(x, ys, xLabel, yLabels);
const options = {
title: title,
series: {
1: {
lineWidth: 3,
pointSize: 0,
curveType: 'function'
},
},
legend: 'none'
};
const chart = new google.visualization.ScatterChart(parentElement);
chart.draw(data, options);
}
}
main();
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="scatter-line-chart"></div>

RangeSelector display error when data is updated on zoomCallback

I am trying to update the charts data after zooming. This works so far using the zoomCallback. But when I use the range selector for zooming,
the range selector is not displayed correctly anymore. See the fiddle when using the range selector.
var data = [[1, 4, 5, 6], [2, 5, 6, 8], [3, 7, 4, 2], [4, 9, 6, 4]];
var gra = new Dygraph(
document.getElementById("chart"),
data,
{
labels: ["X", "Y1", "Y2", "Y3"],
hideOverlayOnMouseOut : false,
showRangeSelector: true,
interactionModel: Dygraph.defaultInteractionModel,
rangeSelectorHeight: 30,
connectSeparatedPoints: true,
legend: 'always',
labelsDivWidth: 350,
zoomCallback: function (minX, maxX, yRanges) {
console.log("ZoomCallback!");
updateDataOnZoom();
},
}
);
function updateDataOnZoom() {
var newData = [];
for (var i = 0; i < data.length; i++) {
var newDataElement = [data[i][0]]; // use old Y-Value
for (var j = 1; j < data[i].length; j++) {
newDataElement.push(data[i][j] + 100); // calculate new X-Values
}
newData.push(newDataElement);
}
gra.updateOptions({
file: newData
});
}
Is there a way to solve this display error of the range selector?
Thanks in advance

Highcharts data set array

I have a chart in highcharts and i'm experiencing trouble passing through data. Right now the problem is the graph is completely vertical, and it is receiving the wrong points for the graph. Its saying its totals are 80, and 2011. The totals are supposed to be 50, and 80.
var myarrays = [2011, 1, 12, 50, 2011, 2, 13, 80];
data:
(function () {
var data = [];
for (var i = 0; i < myarrays.length; i++)
{
data.push(myarrays[i], myarrays[i + 1], myarrays[i+2], myarrays[i+3]);
i+2;
}
return data;
}())
The out put is supposed to return, two sets because the series takes in 4 parameters,
[2011, 1, 12, 50]
[2011, 2, 13, 80]
Also when i manually pass in variables, the format that seems to work is
[[Date.UTC(2011, 7, 11), 101]
So is there any way to turn the return to the above format?
var myarrays = [2011, 1, 12, 50, 2011, 2, 13, 80];
$(function() {
$('#container').highcharts({
chart: 'spline',
},
series: [{
name: 'MySeries',
data:
(function() {
var data = [];
for (var i = 0; i < myarrays.length; i++) {
data.push(myarrays[i], myarrays[i + 1], myarrays[i + 2], myarrays[i + 3]);
i +=3;
}
return data;
}]
});
)]);
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px"></div>
A data can be provided to the spline series in the following forms...
data = [y1, y2, ..., yn];
data = [[x1, y1], [x2, y2], ..., [xn, yn];
data = [[name1, y1], [name2, y2], ..., [namen, yn]];
data = [{x: x1, y: y1}, {x: x1, y: y2}, ... {x: xn, y: y2}];
where x and y values are numbers and name values are strings. If x values are not included then the x values are automately calculated starting at 0 and incrementing by 1.
In your example, the myarray has the form [year1, month1, day1, total1, year2, month2, day2, total2, ...] where every four values represent a single data point in the chart. You need to combine the year, month, and day values into a single number or string value which will then be used as the x or name value for the data point. The total value will be used as the y value for the data point. The code might then look something like...
var myarrays = [2011, 1, 12, 50, 2011, 2, 13, 80];
$(function() {
$('#container').highcharts({
chart: {
type: 'spline'
},
series: [{
name: 'MySeries',
data: (function() {
var data = [];
for (var i = 0; i + 3 < myarrays.length; i += 4) {
var name = myarrays[i] + "/" + myarrays[i + 1] + "/" + myarrays[i + 2];
var y = myarrays[i+3];
data.push([name, y]);
}
return data;
})()
}]
});
});

Categories

Resources