Remi Sture Remi Sture - 2 months ago 28
Javascript Question

How to show current value on two x-axis using Highcharts?

I'm trying to make a graph of one of my training sessions, and want to show the heart rate as y-axis, and time and distance as two x-axises.

I'm able to create axises for both the time and distance, but i'm not sure how to populate the data. Now am I adding the heart rate data for both the distance and the time, and that seams to screw up the presentation, since the data points are doubled up.

What is the best way of keeping the two x-axises independent of each other, and only adding the data for time, distance and heart rate once?

I want the tooltip to display something like this:

Time: 00:19:59
Distance: 5607.2 m
Heart Rate: 190


Demo: http://jsfiddle.net/remisture/4js1nx8z/

$(function() {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});

$.getJSON('http://www.json-generator.com/api/json/get/bTSFRnarqW?indent=2&callback=?', function(jsonData) {

$('#container').highcharts({
chart: {
type: 'area',
marginRight: 10
},
title: {
text: '20:00, 5611 m'
},
xAxis: [{
title: {
text: 'Time'
},
type: 'datetime',
tickPixelInterval: 50
}, {
title: {
text: 'Distance'
},
opposite: true
}],
yAxis: {
title: {
text: 'Heart rate'
}
},
tooltip: {
formatter: function() {
var s = [];
s.push("<b>Time:</b> " + Highcharts.dateFormat('%H:%M:%S', this.points[0].x));
$.each(this.points, function(i, point) {

s.push('<b>' + point.series.name + '</b>: ' + point.y);

});

return s.join('<br/>');
},
shared: true
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
xAxis: 0,
name: 'BPM',
data: (function() {
var data = [],
time,
i;

for (i = 0; i < jsonData.length; i++) {
time = new Date(1970, 0, 1);
time.setSeconds(jsonData[i]['Time (seconds)']);
data.push({
x: time,
y: jsonData[i]['Heart Rate']
});
}

return data;
})()
}, {
xAxis: 1,
name: 'BPM',
data: (function() {
var data = [];

for (i = 0; i < jsonData.length; i++) {
data.push({
x: jsonData[i]['Distance (meters)'],
y: jsonData[i]['Heart Rate']
});
}

return data;
})()
}]
});
});
});

});


Thank you.

Answer

Ok, after re-reading and looking at the data, I think I see what you want.

It seems like the relationship between time and distance is strong enough, that for your purposes it's not a problem, but be aware that the value plotted might not always completely match the axis values.

I would do it this way

1) Get the max distance value ahead of time (I cheated in the example and hard-coded it after looking at the data), and set it as the Distance xAxis max value

2) Set a dummy series on that x axis to make it display properly, with an empty data array

3) Set the distance as a third parameter in your primary data series, and call it out in the tooltip that way

So, for the axes:

xAxis: [{
    title: {
      text: 'Seconds'
    },
  }, {
    opposite: true,
    min: 0,
    max: 5607, <-- get this from the data ahead of time
    title: {
      text: 'Distance'
    },
  }]

and then the series:

series: [{
    name: 'BPM',
    data: (function() {
      var data = [];
      for (i = 0; i < jsonData.length; i++) {
        data.push({
          x: jsonData[i]['Time (seconds)'],
          y: jsonData[i]['Heart Rate'],
                        'Distance': jsonData[i]['Distance (meters)']
        });
      }
      return data;
    })()
  }, {
    xAxis: 1,
    data: []
  }]

And then the tooltip:

tooltip: {
    crosshairs: true,
    formatter: function() {
        return  '<b>Time: </b>'+ this.point.x
                +'<br/><b>BPM: </b>'+ this.point.y
                +'<br/><b>Distance: </b>'+ this.point.Distance;
    }
  }      

Fiddle:

Output:

screenshot

Comments