Highcarts custom legend - highcharts

How can I customize the legends
From
To this

check highcharts legend api options.You can further customize with desired css. use proper svg image (background color is taken from chart itself)
legend: {
align: 'right',
verticalAlign: 'top',
layout: 'vertical',
x: -50,
y: 120,
symbolPadding: 0,
symbolWidth: 0.1,
symbolHeight: 0.1,
symbolRadius: 0,
useHTML: true,
symbolWidth: 0,
labelFormatter: function() {
if(this.name=="Microsoft Internet Explorer"){
return '<div style="width:200px;"><span style="float:left; margin-left:10px"><img src = "http://cdn.onlinewebfonts.com/svg/img_508736.svg" width = "40px" height = "40px" style="background-color:' + this.color + ';"></span><span style="float:right;padding:9px">' + this.percentage.toFixed(2) + " " + this.y + '%</span></div>';
}
if(this.name=="Chrome"){
return '<div style="width:200px;"><span style="float:left; margin-left:10px"><img src = "http://cdn.onlinewebfonts.com/svg/img_159842.svg" width = "40px" height = "40px" style="background-color:' + this.color + ';"></span><span style="float:right;padding:9px">' + this.percentage.toFixed(2) + " " + this.y + '%</span></div>';
}
if(this.name=="Firefox"){
return '<div style="width:200px;"><span style="float:left; margin-left:10px"><img src = "http://cdn.onlinewebfonts.com/svg/img_261106.svg" width = "40px" height = "40px" style="background-color:' + this.color + ';"></span><span style="float:right;padding:9px">' + this.percentage.toFixed(2) + " " + this.y + '%</span></div>';
}
},
itemStyle: {
color: '#ffffff',
fontWeight: 'bold',
fontSize: '19px'
}
},
Fiddle demo

You can modify legend. To display custom icons in place of legend symbols, you need to set legend.useHTML with true value, hide symbol with:
.highcharts-legend-item rect {
visibility: hidden;
}
and use labelFormatter. Take a look at the example posted below.
API Reference:
http://api.highcharts.com/highcharts/legend
Example:
http://jsfiddle.net/2trc1gv9/

Related

On Mouse over on the high chart data the tool tip value should be displayed next to legend label

I am using high chart in my project. Currently when user mouse over on the data points the tool tip will be displayed top to the data points. Some times the data are big and the tool tip will look very big, hence user wants to display the tool tip value next to the legend title during mouse over of the data points.
Example Legends should look like below:
Female % 23 Male % 22
Here 23 and 22 are the data points value which should be printed next to legend label when we mouse over on the data points.
The 23 and 22 value should be changed as per the mouse over on the data points.
enter code here
primaryChart = $('#container').highcharts('StockChart', {
chart: {
// my code
},
yAxis: [{
// my code
}],
xAxis: {
// my code
},
plotOptions: {
// my code
},
tooltip: {
//enabled: false,
followPointer: false,
useHTML: true,
formatter: function () {
//debugger;
var precision;
var s = '<b>' + Highcharts.dateFormat('%A, %b %e %Y, %H:%M:%S', new Date(this.x)) + '</b>';
$.each(this.points, function () {
precision = GetTooltipData(this.series.options.paramID);
s += '<br/ ><span style="color:' + this.series.options.color + '">' + this.series.name + '</span> : ' + parseFloat(this.y.toFixed(precision)) + ' ' + this.series.yAxis.axisTitle.textStr;
// s += "<div class='comment_filter'><a class='comments_buble' href='#' data-series='" + this.point.index + "'>Comment</a></div>";
});
return s;
},
shared: true
},
series: chartData,
rangeSelector: {
selected: 4,
inputEnabled: false,
buttonTheme: {
visibility: 'hidden'
},
labelStyle: {
visibility: 'hidden'
}
},
legend: {
enabled: true,
layout: 'horizontal',
align: 'left',
borderColor: '#909090',
verticalAlign: 'top'
},
credits: {
enabled: false
}
});
You can use positioner function for tooltip to place it next to a legend:
tooltip: {
positioner: function() {
var legend = this.chart.legend,
x = legend.group.translateX + legend.legendWidth,
y = legend.group.translateY;
return {
x: x,
y: y
};
},
...
}
Live demo: https://jsfiddle.net/BlackLabel/3rsp4bdy/
API Reference: https://api.highcharts.com/highcharts/tooltip.positioner
enter code here
tooltip: {
followPointer: true,
useHTML: true,
split: false,
formatter: function () {
var s = '<span>' + this.series.name +'</span>';
this.series.legendItem.element.innerHTML = s;
return false;
},
shared: true,
},

Draw another chart/or series on mouse hover in HighStock

I have an indicator which is a function of x, y.
How can i draw this indicator on top of chart?
Lets say here https://jsfiddle.net/yv3pehj8/
plotOptions: {
series: {
point: {
events: {
mouseOver: function () {
var chart = this.series.chart;
if (!chart.lbl) {
chart.lbl = chart.renderer.label('')
.attr({
padding: 10,
r: 10,
fill: Highcharts.getOptions().colors[1]
})
.css({
color: '#FFFFFF'
})
.add();
}
chart.lbl
.show()
.attr({
text: 'x: ' + this.x + ', y: ' + this.y
});
}
}
}
Instead of printing x,y value on the corner, I wanted to draw a line at an angle of 45 degrees to the hover point ranging from [x-10, x+10]. How could I do it in the most performant way?
TIA
EDIT
Many thanks for the solution. To make it a bit more complicated. i want to reach the following effect as seen in this image []
i want to draw the blue/red curves as you see in the image on mouse hover.. Would you happen to have a solution for this #ppotaczek??
Instead of rendering the label, you can render a path:
plotOptions: {
series: {
point: {
events: {
mouseOver: function() {
var chart = this.series.chart,
path = [
'M',
chart.plotLeft + this.plotX - 10,
chart.plotTop + this.plotY - 10,
'L',
chart.plotLeft + this.plotX + 10,
chart.plotTop + this.plotY + 10
];
if (!chart.lbl) {
chart.lbl = chart.renderer.path(path)
.attr({
'stroke-width': 2,
stroke: 'red'
})
.add();
}
chart.lbl
.show()
.attr({
d: path
});
}
}
},
...
}
}
Live demo: https://jsfiddle.net/BlackLabel/zo46fuxb/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#path

How to put shadow inside of bar chart in highcharts?

How to put shadow inside of bar chart like box-shadow inset(css) in hightcharts as image below.
Thank you. Have a good day~
enter image description here
You can use two overlap series, one with default shadow property and translate both of them by a few pixels in load event:
Highcharts.chart('container', {
chart: {
...,
events: {
load: function() {
this.series[0].points[0].graphic.attr({
translateX: -2
});
this.series[1].points[0].graphic.attr({
translateX: -2
});
}
}
},
...,
series: [{
...,
data: [100],
shadow: {
color: 'gray',
opacity: 0.8,
width: 2
}
}, {
data: [50]
}]
});
Live demo: http://jsfiddle.net/BlackLabel/b7hp0r6s/
API Reference: https://api.highcharts.com/highcharts/series.bar.shadow
Unfortunately, Highcharts doesn't have an inset shadow implemented in the core. However, it can be done by adding custom logic to Highcharts.SVGElement.prototype.shadow method. Check the code and demo posted below and let me know if something is unclear for you.
Additionally, to add a partial fill to columns with the inner shadow you have to make a custom column elements and insert them to the DOM between shadows and particular points.
Code:
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
(function(H) {
H.SVGElement.prototype.shadow = function(shadowOptions, group, cutOff) {
var shadows = [],
i, shadow, element = this.element,
strokeWidth, shadowWidth, shadowElementOpacity,
// compensate for inverted plot area
transform,
elemBBox = element.getBBox(),
translateX,
translateY;
if (!shadowOptions) {
this.destroyShadows();
} else if (!this.shadows) {
shadowWidth = H.pick(shadowOptions.width, 3);
shadowElementOpacity = (shadowOptions.opacity || 0.15) /
shadowWidth;
transform = this.parentInverted ?
'(' + H.pick(shadowOptions.offsetY, 1) * -1 + ', ' +
H.pick(shadowOptions.offsetX, 1) * -1 + ')' :
'(' + H.pick(shadowOptions.offsetX, 1) + ', ' +
H.pick(shadowOptions.offsetY, 1) + ')';
if (!shadowOptions.inside) {
for (i = 1; i <= shadowWidth; i++) {
shadow = element.cloneNode(0);
strokeWidth = (shadowWidth * 2) + 1 - (2 * i);
H.attr(shadow, {
stroke: (shadowOptions.color ||
'#000000'),
'stroke-opacity': shadowElementOpacity * i,
'stroke-width': strokeWidth,
transform: 'translate' + transform,
fill: 'none'
});
shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow');
if (cutOff) {
H.attr(shadow, 'height', Math.max(H.attr(shadow, 'height') - strokeWidth, 0));
shadow.cutHeight = strokeWidth;
}
if (group) {
group.element.appendChild(shadow);
} else if (element.parentNode) {
element.parentNode.insertBefore(shadow, element);
}
shadows.push(shadow);
}
} else {
for (i = shadowWidth; i >= 1; i--) {
shadow = element.cloneNode(0);
translateX = i / 2 - shadowOptions.offsetY;
translateY = i / 2 - shadowOptions.offsetX;
H.attr(shadow, {
stroke: (shadowOptions.color ||
'#000000'),
'stroke-opacity': shadowElementOpacity * (shadowWidth - i + 1),
'stroke-width': i,
transform: 'translate(' + translateX + ',' + translateY + ')',
fill: 'none'
});
H.css(shadow, {
width: elemBBox.width - i,
height: elemBBox.height - i,
});
shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow');
if (cutOff) {
H.attr(shadow, 'height', Math.max(H.attr(shadow, 'height') - strokeWidth, 0));
shadow.cutHeight = strokeWidth;
}
if (group) {
group.element.appendChild(shadow);
} else if (element.parentNode) {
insertAfter(shadow, element);
}
shadows.push(shadow);
}
}
this.shadows = shadows;
}
return this;
};
})(Highcharts)
Highcharts.chart('container', {
chart: {
type: 'column',
inverted: true,
events: {
render: function() {
var chart = this,
yAxis = chart.yAxis[0],
partialFillWidth,
elem,
bBox;
if (chart.customElements && chart.customElements.length) {
chart.customElements.forEach(custElem => {
custElem.parentNode.removeChild(custElem);
})
chart.customElements.length = 0;
} else {
chart.customElements = [];
}
chart.series[0].points.forEach(point => {
bBox = point.graphic.getBBox();
elem = point.graphic.element.cloneNode(0);
partialFillWidth = yAxis.toPixels(point.partialFill);
Highcharts.attr(elem, {
fill: point.partialFillColor,
transform: 'translate(0, ' + (bBox.height - (point.partialFill / point.y) * bBox.height) + ')'
});
Highcharts.css(elem, {
height: (point.partialFill / point.y) * bBox.height
});
insertAfter(elem, point.graphic.element);
chart.customElements.push(elem);
});
}
}
},
title: {
text: 'Efficiency Optimization by Branch'
},
xAxis: {
categories: [
'Seattle HQ',
'San Francisco',
'Tokyo'
]
},
yAxis: [{
min: 0,
title: {
text: 'Employees'
}
}, {
title: {
text: 'Profit (millions)'
},
opposite: true
}],
legend: {
shadow: false
},
tooltip: {
shared: true
},
plotOptions: {
column: {
grouping: false,
shadow: false,
borderWidth: 0,
pointPadding: 0,
groupPadding: 0
}
},
series: [{
color: '#efefef',
id: 'main',
data: [{
y: 120,
partialFill: 100,
partialFillColor: '#bbb'
}, {
y: 50,
partialFill: 10,
partialFillColor: '#bbb'
}, {
y: 70,
partialFill: 20,
partialFillColor: '#bbb'
}],
pointPadding: 0.4,
shadow: {
color: 'rgba(0, 0, 0, 0.5)',
opacity: 0.3,
width: 5,
offsetX: 0,
offsetY: 0,
inside: true
}
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/kvrjd48w/
API reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement
https://api.highcharts.com/class-reference/Highcharts#.attr

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/

Tooltip issue on columnrange

Please look at the example. I've created on jsfiidle.
http://jsfiddle.net/cr1t/LdLn2/1/
The issue I'm having is with the tooltip that floats above the graph. The text on the column range seems to have a much higher z-index. But no matter what I try and set it on the div style sheet, it shows threw. I'd like the have the point detail in html, because I want to make it a hyperlink tag.
plotOptions: {
columnrange: {
dataLabels: {
inside: true,
enabled: true,
useHTML: true,
formatter: function () {
if (this.y === this.point.low) {
return '<div style="padding:2px;text-align:center;color:black;overflow:hidden;width:' + (this.point.plotLow - this.point.plotHigh - 4) + 'px">' + this.point.low + '°C - ' + this.point.high + '°C </div>';
}
}
}
}
},
Thanks Anto
I followed the duplicate.
I managed to get it working the way I wanted with css
http://jsfiddle.net/cr1t/LdLn2/2/
.highcharts-data-labels {
z-index: 1 !important;
}
.highcharts-tooltip span {
background-color:white;
opacity:1;
z-index:9999 !important;
padding:5px
}
.tooltip {
padding:5px
}
and setting the style on the tooltip
tooltip: {
backgroundColor: "rgba(255,255,255,1)",
style: {
padding: '1px'
},
shadow: false,
useHTML: true,
percentageDecimals: 2,
formatter: function () {
return '<div class="tooltop">'+ this.point.category + '<br />' +
'Temprature ' + this.point.low + '°C - ' + this.point.high + '°C </div>'
}
}

Resources