In highcharts.js, how to make custom ticks with an image - highcharts

How would I go about and make custom image and text for an axis tick in highcharts.js? I need a normal number as label for the tick and then a small colored square image (dependant on another variable from a special array of values) displayed below the number? This is what I need to do, see image below

You can create an additional HTML element for rectangles and in 'load' event use color-axis to translate values into background colors.
const colorValues = [5, 9, 14, 15, 1, 4];
Highcharts.chart('container', {
...,
chart: {
events: {
load: function() {
const rectangles = document.getElementsByClassName('label-rect'),
colorAxis = this.colorAxis[0];
[].forEach.call(rectangles, function(rect) {
rect.style.backgroundColor = colorAxis.toColor(rect.dataset.value);
});
}
}
},
xAxis: {
type: 'category',
labels: {
style: {
'text-align': 'center'
},
useHTML: true,
formatter: function() {
return this.pos + '<br/>' +
'<span data-value="' + colorValues[this.pos] +
'" class="label-rect"></span>'
}
}
}
});
Live demo: http://jsfiddle.net/BlackLabel/7146g2r3/
API Reference:
https://api.highcharts.com/highcharts/xAxis.labels
https://api.highcharts.com/highcharts/colorAxis

Related

How to add separate annotation style tooltip for Highcharts marker?

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

How to hide stackLabel in highcharts when it is bigger than the column

How can I hide a stackLabel (a label above the column) in highCharts when the text in the label is bigger than the column (As you can see in the image below).
I want to show empty string when my data exceeds the column width.
This is part of the code which is responsible for showing the data:
yAxis: {
stackLabels: {
style: {
color: 'black'
},
enabled: true
formatter: function () {
return this.total + " mm ";
}
}
}
Create a function which loop through the stack labels and compare their width with the point's width - according to the comparison hide or show the label.
Function can look like this:
function hideLabel() {
const axis = this.yAxis[0];
const stacks = axis.stacks.column;
const pointWidth = this.series[0].points[0].shapeArgs.width;
Object.keys(stacks).forEach(key => {
const label = stacks[key].label;
label.attr({
visibility: label.getBBox().width > pointWidth ? 'hidden' : 'visible'
});
})
}
Set this function on load and redraw events:
chart: {
type: 'column',
events: {
load: hideLabel,
redraw: hideLabel
}
},
example: http://jsfiddle.net/nq5ke47z/

How do I calculate the total Data values for both and display in Legend

I have created a highcharts type column for 2 series Men and Women. I want to display the total counts which is Installs and display below Legend as shown in the image.
How do I use the HTML with Icons with the total values.
Here is my code for the highcharts and JSFiddle
$(function () {
$('#stats-container').highcharts({
chart: {
type: 'column'
},
credits: {
enabled: false
},
title: null,
xAxis: {
categories: ['15-20', '20-25', '25-30', '30-35', '35-40', '40-45', '45-50']
},
yAxis: {
min: 0,
max: 90,
pointInterval: 30,
labels: {
formatter: function () {
return this.value + 'K';
}
},
title: null
},
tooltip: {
formatter: function () {
return '<b>' + this.x + '</b><br/>' +
this.series.name + ': ' + this.y;
}
},
navigation: {
buttonOptions: {
enabled: false
}
},
legend: {
enabled: true,
align: 'center',
verticalAlign: 'top',
layout: 'horizontal'
},
series: [{
name: 'Men',
color: '#79ccde',
data: [57.56, 82, 32, 28, 12, 13, 7],
stack: 'male'
}, {
name: 'Women',
color: '#8787f5',
data: [33.66, 60, 35, 15, 10, 16, 9],
stack: 'female'
}]
});
});
How can I achieve the same legend with total counts and custom HTML?
For calculating total values of both series and displaying it in your legend you can use legend.labelFormatter:
http://api.highcharts.com/highcharts#legend.labelFormatter
Inside labelFormatter function you can iterate over all of your series points and add its value to sum you want to show in your label.
If you want to add image to your legend label you need to set legend.useHTML to true:
http://api.highcharts.com/highcharts#legend.useHTML
Then you can format your legend as HTML div. For example:
labelFormatter: function() {
var target = '<br>Target: ' + this.userOptions.target || 0,
installs = 1,
string, img;
Highcharts.each(this.userOptions.data, function(p, i) {
installs += p;
});
if (this.name === "Women") {
img = '<img src = "http://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Woman_Silhouette_52.svg/2000px-Woman_Silhouette_52.svg.png" style = "width:45px"/> ';
} else if (this.name === "Men") {
img = '<img src = "https://upload.wikimedia.org/wikipedia/commons/1/17/Human_outline.svg" style = "width:20px"/> ';
}
string = '<div style = "width: 200px">' + '<div class = "leg">' + img + '</div>' + '<div class = "leg">' + this.name + target + '<br>Installs: ' + installs + '</div>' + '</div>';
return string
}
For hiding standard legend symbol you can set its width to 0:
http://api.highcharts.com/highcharts#legend.symbolWidth
If you want to show your tooltip the same way as you show in your image, you can use tooltip.shared property:
http://api.highcharts.com/highcharts#tooltip.shared
example:
http://jsfiddle.net/am6zjhrj/10/

Highcharts - remove points from series

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;
})()
}]
});
});
});

Set the with of xAxis label to 50% on a Highcharts BarChart

Is there way to set the label of an Bar Chart to 50% of the charts width? I've tried this but it does not work:
xAxis: {
categories: [],
labels: {
formatter: function() {
var text = this.value;
return '<div class="js-ellipse" style="width:100%; overflow:hidden; text-overflow: ellipsis" title="' + text + '">' + text + '</div>';
},
style: {
width: '50%'
},
useHTML: true
}
},
So goal is to have labels on the left side of the bar chart that are 50% of the width of the whole chart container.
You have an option for that in the plotOptions :
plotOptions: {
bar: {
dataLabels: {
enabled: true,
inside: true
// ^^^^^^^^^^^^
}
}
},
The property inside :
For points with an extent, like columns, whether to align the data label inside the box or to the actual value point. Defaults to false in most cases, true in stacked columns.
And an example forked from the official documentation : http://jsfiddle.net/XXB9k/
EDIT :
There is another option to center the x labels (I don't know witch labels your are talking about), but there is a solution not far away from your code :
xAxis: {
...
labels: {
enabled: true,
x: this.width / 2,
}
}
An example : http://jsfiddle.net/QMPkh/
FINAL EDIT :
In fact you can simply use the width of the chart in the label formatter :
labels: {
enabled: true,
formatter: function() {
return '<div style="width:' + (this.axis.width/2) +'px">'+this.value+'</div>';
},
useHTML: true
}
An example to show the result : http://jsfiddle.net/QMPkh/2/
Unfortunately width in percent is not supported, only in pixels.

Resources