I would like highlight the weekend in a timeseries chart. Until now and reading the documentation I think it is two ways of achieving this: plot bands or zones. I just managed to highlight the saturdays and sunday on the x axis(see code below). I would like to plot a band instead.(see 1).
xAxis: {
type: 'datetime',
crosshair: {
width: 2,
color: '#F66',
dashStyle: 'shortdot'
},
labels: {
formatter: function () {
var day = Highcharts.dateFormat('%a', this.value);
if (day == "Sat" || day == "Sun") {
return `<b>${Highcharts.dateFormat('%a %e %b', this.value)}</b>`;
} else {
return Highcharts.dateFormat('%a %e %b', this.value);
}
}
}
}
}
Here is my idea how to add plotBands dynamically based on the used data. I think that everything is clear in the code - if not, feel free to ask.
Demo: https://jsfiddle.net/BlackLabel/6n4ab7jm/
events: {
load() {
let chart = this,
plotBandAr = [],
plotBand = {
color: '#FCFFC5',
};
chart.series[0].points.forEach(p => {
// start from the saturday
if (new Date(p.x).getDay() === 6) {
plotBand.from = p.x
}
// end on the sunday
if (new Date(p.x).getDay() === 0) {
plotBand.to = p.x
}
// add plotBand on monday and reset the plotBand object
if (new Date(p.x).getDay() === 1) {
plotBandAr.push(plotBand)
plotBand = {
color: '#FCFFC5',
};
}
});
chart.xAxis[0].update({
plotBands: plotBandAr
})
}
}
API: https://api.highcharts.com/highcharts/chart.events.load
API: https://api.highcharts.com/class-reference/Highcharts.Axis#update
Related
I am plotting a 3D line chart over time. Each time the count changes at the end of the loop, a new point is plotted for each series. Is there a way to set the value of the legend as the value of count in my example code? The count represents hours since the start of an experiment, so being able to display this is necessary. Thanks!
events: {
load: function() {
var thischart = this;
for (i = 0; i < allpoints.length; i++) {
thischart.addSeries({
enableMouseTracking: false,
lineWidth: 1,
marker: {
enabled: false
},
data: [0, 0, 0]
}, false)
thischart.redraw(false);
}
setInterval(function() {
if (count >= max_data_length) {
if (!pause_at_end) {
for (i = 0; i < allpoints.length; i++) {
thischart.series[i + marker_series_length].setData([0, 0, 0], false);
}
thischart.redraw(false);
count = 1;
} else {
is_paused = true;
document.getElementById('pauseit').value = "Unpause";
}
}
if (!is_paused) {
for (i = 0; i < allpoints.length; i++) {
if (allpoints[i].length > count) {
thischart.series[i + marker_series_length].addPoint([
allpoints[i][count][0], allpoints[i][count][2], allpoints[i][count][1]
], false);
}
}
thischart.redraw(false);
count = count + 4;
}
}, 10)
}
}
You can use series.update method to set new data and change the series name in legend:
chart: {
...,
events: {
load: function() {
var counter = 0,
series = this.series[0];
setInterval(function() {
counter++;
series.update({
data: getRandomData(),
name: 'Name ' + counter
});
}, 1000);
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/7bq21tak/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#update
Thanks ppotaczek! This pointed me in the right direction. I used chart.update instead to update the subtitle. Here is the code I used:
chart.update({
chart: {
inverted: false,
polar: false
},
subtitle: {
style: {
fontSize: '20px'
},
text:'Day:'+ countdays
}
});
Need to add separate tooltip for point marker.
I am using crosshair for displaying tooltip in Highcharts. Also, for some of the series data points I am adding a marker(in yellow circle). I want to know if it is possible to have a custom tooltip on hovering specifically on the marker point, but I would also like to retain the normal crosshair tooltip behavior on the same point (i.e. while hovering outside the yellow marker area for the same data point, tooltip should respect the tooltip formatter and on hovering exactly on the marker tooltip should show a different text related to the marker). Is it possible to achieve?
[My intention is to create a hoverable annotation marker, but at the same time retain the default tooltip behavior for the same point]
Please see the images below to get an idea about the expected behavior. Please ignore the series data, since they are generated dynamically, and is different on every page refresh. What I want to achieve is to have a crosshair tooltip for the '05-Jan-2019' data point, and also show a different looking or custom tooltip when user hovers specifically on the 'yellow' marker for the same data point.
Any suggestions related to alternative ways to achieve this are also welcome.
Here is how I am adding the marker in my series data :
function formatSeriesData(allSeries, annotations, categories) {
for (let i = 0; i <= allSeries.length; i++) {
let serie = allSeries[i];
if (serie && !serie['color']) {
serie = {
...serie,
color: defaultColors[i]
}
allSeries[i] = serie;
}
//add annotations - if present
if (serie && annotations && annotations.length) {
const applicableAnnotations = _.filter(annotations, {
name: serie.name
});
const annotationDates = _.map(applicableAnnotations, 'date'); //get all annotation dates
let modifiedDataArray = [];
let dataArray = serie.data; //get all series data
for (let j = 0; j < dataArray.length; j++) {
let dateForValue = categories[j]; //get the date corresponding to the value
let annotation = _.find(applicableAnnotations, {
date: dateForValue
});; //pick the annotation object
let ptObj = {
dimension: "",
y: dataArray[j]
};
if (annotation && annotation.annotation) {
ptObj["marker"] = {
enabled: true,
radius: 6,
fillColor: '#FDBE2C',
symbol: 'circle'
};
}
modifiedDataArray.push(ptObj);
}
serie = {
...serie,
data: modifiedDataArray
}
allSeries[i] = serie;
}
}
console.log("allSeries ", allSeries);
return allSeries;
}
To achieve the wanted result you can create a chart with two series - line with disabled enableMouseTracking and scatter with default tooltip and mouse events to control the display of crosshair:
Highcharts.chart('container', {
series: [{
data: [1, 2, 3, 4],
enableMouseTracking: false
}, {
color: 'yellow',
events: {
mouseOver: function() {
this.xAxis.update({
crosshair: {
width: 0,
label: {
enabled: false
}
}
});
},
mouseOut: function() {
this.xAxis.update({
crosshair: {
width: 1,
label: {
enabled: true
}
}
});
}
},
marker: {
radius: 8,
symbol: 'circle'
},
stickyTracking: false,
data: [{
x: 2,
y: 3
}]
}],
xAxis: {
crosshair: {
label: {
enabled: true
},
snap: false
}
}
});
Live demo: http://jsfiddle.net/BlackLabel/k83u0spd/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Axis#update
https://api.highcharts.com/highcharts/series.line.enableMouseTracking
https://api.highcharts.com/highcharts/series.line.stickyTracking
I am using 2 arrays with some numbers and getting the percentage. What I would like to do is if both array indexes are 0 the I would like to set the Label to read "No Data".
I know I need to get the current column(point) index or something similar, I've tried using formatters to do this.
Anyways I imagine the code something like this.
xAxis: {
categories: trebleNotes,
labels: {
rotation: -45,
align: 'right',
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
},
formatter: function () {
if(array1[currentColumn] == 0 && array2[currentColumn] == 0){
return("NO DATA");
}else{
return(this.value);
}
},
}
},
I am not sure how to get the currentColumn index and use that to do the formatting. I hope this makes sense.
If I understand you correctly, wouldn't you just want the index of the category at this.value?
labels: {
formatter: function() {
var currentColumn = -1;
for (var idx = 0; idx < this.axis.categories.length; idx++){
if (this.axis.categories[idx] == this.value){
currentColumn = idx;
break;
}
}
console.log(currentColumn);
return this.value;
}
}
Is it possible to remove certain points from a series?
I'm looking for some way to draw a chart with a fixed back period,
something like: the last 1 hour.
I know how to add points using dynamic update:
http://www.highcharts.com/demo/dynamic-update
But in my case the time interval between points is not constant,
so I can't just use the shift option of addPoint.
Thanks,
Omer
If you want to have the same, you can use the same logic as in addPoint, see: http://jsfiddle.net/JKCLx/1/
However, why can't you just use shift argument in addPoint()?
I think I found a partial answer to my own question:
I can iterate over the series datapoints like this:
http://api.highcharts.com/highcharts#Series.data
and then call point.Remove.
The problem with this solution is that it does not draw monitor style like in the example,
but rather it redrwas the entire chart on each change.
http://jsfiddle.net/JKCLx/
$(function () {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint([x, y], true, false);
// series.data[0].remove(false);
series.data[0].remove(true);
}, 1000);
}
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
})()
}]
});
});
});
After any sort of zoom (mouse drag, range selector, date input) the datetime returned from the point click event is usually incorrect. I've not yet found this problem when using an area chart, have found it using both bar and column chart.
To recreate: run the fiddle, zoom using the mouse across a few of the columns, click a datapoint. The alert will show the datetime returned. Notice it's different from the tooltip (which is correct).Usually fails after first click, even for the same datapoint.
BTW useUTC setting doesn't matter.
Fiddle: http://jsfiddle.net/jrEDT/
Code for completeness:
$(function() {
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
names = ['MSFT'],
colors = Highcharts.getOptions().colors;
$.each(names, function(i, name) {
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename='+ name.toLowerCase() +'-c.json&callback=?', function(data) {
seriesOptions[i] = {
name: name,
data: data,
type: 'column'
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if (seriesCounter == names.length) {
createChart();
}
});
});
// create the chart when all data is loaded
function createChart() {
Highcharts.setOptions({
global: {
useUTC: false // datetime reflects time on db (ie, local) rather than GMT
}
});
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
zoomType: 'x'
},
exporting: {
enabled: false
},
rangeSelector: {
selected: 4
},
yAxis: {
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}],
offset: 25
},
plotOptions: {
series: {
cursor: 'pointer',
allowPointSelect: true,
point: {
events: {
click: function() {
var series = this.series.name;
var utc = this.x;
var d = Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x);
alert(d);
}
}
}
}
},
tooltip: {
formatter:function(a,b,c){
var d = Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x);
return d;
},
enable:true
},
series: seriesOptions
});
}
});
Thanks!
Have you tried to disable datagrouping http://api.highcharts.com/highstock#plotOptions.series.dataGrouping ?