What is the recommended way to resize a Highchart that is embedded in an HTML page?
I set the <div> that contains the chart (the chart.options.renderTo) (and the Highcharts div itself) to style.resize="both" but that doesn't seem to take (I suspect because the Highchart URL is in the bottom right of the chart). Specifically I'm looking for the recommended UI cue.
Suggestions?
You need to set same padding on the chart container to see the resize. If the chart container dimensions are changed, then you need to call chart.reflow method:
CSS:
#container {
width: 400px;
height: 400px;
background: #e2eaad;
margin: 0 auto;
resize: both;
padding: 10px;
}
JS:
var chart = Highcharts.chart('container', {
series: [{
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}]
});
document.getElementById('container').addEventListener("click", function() {
chart.reflow();
});
Live demo: http://jsfiddle.net/BlackLabel/pnq8w6tr/
API: https://api.highcharts.com/class-reference/Highcharts.Chart#reflow
Related
I have a horizontal bar chart with negative and positive values,
I noticed that gridlines have a slight offset to the left (maybe they get rounded?). Here is an image that illustrates my problem:
I tried to reproduce it in fiddle, but got slightly different result (please export png to see the image). It's hard to notice but negative bars don't start from zero.
So I am curios to know what is the root cause of the problem and potential fix you may suggest.
Thanks in advance!
Highcharts.chart('container', {
chart: {
type: 'bar',
styledMode: true,
events: {
load: function(){
const chart = this;
const gridLines = chart.yAxis[0].gridGroup.element.querySelectorAll('path');
console.log(gridLines);
const yTicks = chart.yAxis[0].ticks;
for(let tick of Object.keys(yTicks)){
if(yTicks[tick].pos === 0) {
const zeroGridLine = yTicks[tick].gridLine.element;
zeroGridLine.classList.replace('highcharts-grid-line','zero-line');
if(chart.seriesGroup) chart.seriesGroup.element.appendChild(zeroGridLine)
break;
}
}
}
}
},
title: {
text: 'title'
},
xAxis: {
categories: ['Medical care',
'Shelter',
'Personal services',
'Education',
'Furnishings',
'Communication',
'Recreation',
'Fuels and utilities',
'Apparel',
'Transportation',],
lineWidth: 1,
labels: {
align: 'left',
reserveSpace: true,
step: 1,
x:-5,
/* max: 9.5,
min: -0.5, */
style: {
whiteSpace: 'wrap',
textOverflow: 'visible'
}
}
},
yAxis: {
tickWidth: 1
},
series: [{
name: 'April 2020',
data: [
4.81, 2.62, 2.53, 2.15, 1.31, 1.12, 0.94, -0.35, -3, -8]
}, {
name: 'Jan 2020',
data: [4.48, 3.32, 2.11, 2.17, 0.66, 0.93, 1.41, 0.57, -1.26, 2.87]
}]
})
#import 'https://code.highcharts.com/css/highcharts.css';
#container {
min-width: 300px;
max-width: 300px;
height: 300px;
margin: 1em auto;
}
.highcharts-xaxis-labels {
font-size: 15px;
}
.zero-line {
stroke: black;
stroke-width: 1;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="height: 400px"></div>
I think that it is a bug. I reported it on the Highcharts Github issue channel where you can follow this thread or add your own opinion about this behaviour. The core developers will respond you.
https://github.com/highcharts/highcharts/issues/14302
I have a simple line chart with a legend aligned to the right. Legend width is set based on the legend item content, if the content doesn't exceed 25% of the width of the chart, it stays as it is. But if it exceeds - 25% is applied. The code for this is here.
The problem is that I am facing a situation when legend text has long string without white spaces in between - like PricewaterhouseCooper, the text gets cutoff - which is expected result based on the code. However I wanted to eliminate this scenario and let it exceed 25% if there is a string which width is wider than 25%. Do you have suggestion how better approach this problem?
Thanks!
My suggestion is using custom legend HTML to use custom styling for it. Highchart can be very strong at custom style for your chart.
I created this Fiddle for an example of it.
In my example, I used "min-width" and "max-width" based on percent of your container width. Also different "font-family" can cause a different results.
<script src="https://code.highcharts.com/highcharts.js"></script>
<style>#import 'https://code.highcharts.com/css/highcharts.css';
#container {
min-width: 300px;
max-width: 500px;
height: 300px;
margin: 1em auto;
}
</style>
<div id="container"></div>
<script>
Highcharts.chart('container', {
chart: {
styledMode: true,
events: {
load: function() {
var chart = this,
legend = chart.legend,
legendMaxWidth =
Highcharts.relativeLength(legend.options.maxWidth, 1) * chart.chartWidth;
/*if (legend.legendWidth > legendMaxWidth) {
legend.update({
width: legend.options.maxWidth
});
}*/
}
}
},
legend: {
align: 'right',
layout: 'proximate',
maxWidth: '25%',
width: '25%',
/* use custom html */
useHTML: true,
labelFormatter: function () {
return '<span title="' + this.name + '" style="max-width:110px;min-width:75px;display:block;word-wrap: break-word;white-space: normal;letter-spacing: 0.5px;">' + this.name + '</span>';
}
},
series: [{
name: 'PricewaterhouseCoopers',
data: [1, 4, 3, 5],
},{
name: 'Pricewaterhouse Coopers copy',
data: [2, 1, 0, 3],
},
{
name: 'Deloitteverylongtexthere',
data: [3, 5, 3, 1],
}
]
});
</script>
I'm adding a series to my Highcharts chart. I'm trying to make that specific series' tooltip have a certain shape. I know that you can change the tooltip shape for the whole chart, but I want each series to have a specific one. How do I accomplish this.
P.S. This doesn't work:
chart.addSeries({
...stuff...
tooltip: {
shape: "triangle-down"
}
});
The API states that only a subset of properties are used from the Series.tooltip options. The shape attribute is not one of them. However, one way to get around this is to extend the Tooltip.refresh function to do a full redraw of the tooltip, and supplying the shape argument there.
For example:
$(function() {
(function (H) {
H.wrap(H.Tooltip.prototype, 'refresh', function (proceed, pointOrPoints, mouseEvent) {
this.update({ shape: pointOrPoints.series.tooltipOptions.shape });
return proceed.apply(this, Array.prototype.slice.call(arguments, 1));
});
}(Highcharts));
Highcharts.chart('container', {
tooltip: {
shape: 'triangle-down', // Global shape
},
series: [{
tooltip: {
shape: 'diamond' // Specific shape for series
},
data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
}, {
tooltip: {
shape: 'circle' // Specific shape for series
},
data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
}, {
tooltip: {
shape: 'square' // Specific shape for series
},
data: [0, 0, 7988, 12169, 15112, 22452, 34400, 34227]
}, {
data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111]
}],
});
});
#container {
min-width: 310px;
max-width: 800px;
height: 400px;
margin: 0 auto
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
This shows overriding the Tooltip.refresh and then using pointOrPoints.series.tooltipOptions.shape to fetch the tooltip.shape for the specific series. Note that this will be more resource intensive as the tooltip is recreated for each tooltip.refresh, as the shape can only be altered upon label creation.
I am using Highcharts 6.0.1 in styled mode and trying to set a custom color for a specific point and the correspondent halo.
I need to be able to dynamically append a class name to some of the points in the series. These points need to be displayed in a different color, thus overriding the default series colors (.highcharts-color-i).
I managed to override the color of a specific the point, as the point object accepts an optional className which can then be used to style the color of the slice in the pie chart.
The css rule for the halo though, is set to inherit the color of the correspondent .highcharts-color-i and since it is not a child element of the point it cannot inherit the custom class name.
Here is a code snippet. You can see that when hovering over the grey slice, the halo is using the default color.
Highcharts.chart('container', {
title: {
text: 'Pie point CSS'
},
tooltip: {
pointFormat: '<b>{point.percentage:.1f}%</b>'
},
series: [{
type: 'pie',
keys: ['name', 'y', 'className'],
data: [
['Point1', 29.9,],
['Point2', 14.5],
['Point3', 11.5],
['Point4', 54.5, 'custom-style'],
],
}]
});
#import 'https://code.highcharts.com/css/highcharts.css';
#container {
height: 400px;
max-width: 800px;
min-width: 320px;
margin: 0 auto;
}
.highcharts-tooltip {
stroke: gray;
}
.highcharts-pie-series .highcharts-point {
stroke: #EDE;
stroke-width: 2px;
}
.highcharts-pie-series .highcharts-data-label-connector {
stroke: silver;
stroke-dasharray: 2, 2;
stroke-width: 2px;
}
.highcharts-pie-series .highcharts-point.custom-style,
.highcharts-pie-series .highcharts-data-label-connector.custom-style {
stroke: lightgray;
stroke-dasharray: white;
stroke-width: 1px;
fill:lightgray;
}
<script src="https://code.highcharts.com/js/highcharts.js"></script>
<div id="container"></div>
Halo is a property of a series (not a point - only one halo can exist per series). In DOM tree it's on the same level as the rest of the points.
You can use point's mouseOver event for setting the color of the halo:
plotOptions: {
series: {
point: {
events: {
mouseOver: function() {
var point = this,
className = point.className;
if (className) {
point.series.halo.attr({
class: 'highcharts-halo custom-style'
});
}
}
}
}
}
}
.highcharts-halo.custom-style selector is used for styling via CSS.
Live demo: http://jsfiddle.net/kkulig/fv0zen7L/
API reference:
https://api.highcharts.com/highcharts/plotOptions.pie.events.mouseOver
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
I need to add in another row of text on each of the tooltips I'm displaying (on an area chart). I've included a screenshot to illustrate what I'm hoping to do.
My current chart:
The chart with the additional text added. (This is what I'm trying to do):
I'm hoping to do this without having to use a third party JS for custom tooltips. Is there any way to just add another row of text-based content to be displayed in the default tooltips?
Any help is greatly appreciated.
Have a look at https://developers.google.com/chart/interactive/docs/roles#whatrolesavailable:
Additional tooltip rows are what you are looking for!
The example:
label: 'Year', 'Sales', null, 'Expenses', null
role: domain, data, tooltip, data, tooltip
'2004', 1000, '1M$ sales, 400, '$0.4M expenses
in 2004' in 2004'
'2005', 1170, '1.17M$ sales, 460, '$0.46M expenses
in 2005' in 2005'
'2006', 660, '.66$ sales, 1120, '$1.12M expenses
in 2006' in 2006'
'2007', 1030, '1.03M$ sales, 540, '$0.54M expenses
in 2007' in 2007'
If you enable focusTarget: 'category' in the options. Then the tooltip column becomes a value for the the tooltip of the current x,y dots (which gets rendered the way you want). So you can mimic the value and add the additional text you want. Here is an example what I mean:-
google.setOnLoadCallback(drawChart);
function drawChart() {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Year');
dataTable.addColumn('number', 'Sales');
// A column for custom tooltip content
dataTable.addColumn({type: 'string', role: 'tooltip'});
dataTable.addRows([
['2010', 600,'600: 15% growth'],
['2011', 1500, '1500: 50% growth'],
['2012', 800, '800: -40% growth'],
['2013', 1000, '1000: 25% growth']
]);
var options = { legend: 'none', focusTarget: 'category'};
var chart = new google.visualization.ColumnChart(document.getElementById('col_chart_custom_tooltip'));
chart.draw(dataTable, options);
}
I haven't found a way to add another data row to the default tooltips. You can get close to what you are looking for using HTML tooltips. You do lose the tail on the tooltip though. Here is a JSbin with the solution I used... http://jsbin.com/tovizukabu/3/edit?css,js,output
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Year');
dataTable.addColumn('number', 'Sales');
dataTable.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
dataTable.addColumn('number', 'Expense');
dataTable.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
dataTable.addRows([
['2010', 1500, '<div><strong>2010</strong><br>Date: <strong>00/00/0000</strong><br>Sales: <strong>$600</strong></div>', 600,'<div><strong>2010</strong><br>Date: <strong>00/00/0000</strong><br>Expense: <strong>$600</strong></div>'],
['2011', 500, '<div><strong>2010</strong><br>Date: <strong>00/00/0000</strong><br>Sales: <strong>$600</strong></div>', 1500, '<div><strong>2011</strong><br>Date: <strong>00/00/0000</strong><br>Expense: <strong>$1,500</strong></div>'],
['2012', 1200, '<div><strong>2010</strong><br>Date: <strong>00/00/0000</strong><br>Sales: <strong>$600</strong></div>', 800, '<div><strong>2012</strong><br>Date: <strong>00/00/0000</strong><br>Expense: <strong>$800</strong></div>'],
['2013', 500, '<div><strong>2010</strong><br>Date: <strong>00/00/0000</strong><br>Sales: <strong>$600</strong></div>', 1000, '<div><strong>2013</strong><br>Date: <strong>00/00/0000</strong><br>Expense: <strong>$1,000</strong></div>']
]);
var options = {tooltip: {isHtml: true}};
var chart = new google.visualization.AreaChart (document.getElementById('tooltip_action'));
chart.draw(dataTable, options);
}
And the CSS...
.google-visualization-tooltip {
border: solid 1px #bdbdbd;
border-radius: 2px;
background-color: white;
position: absolute;
box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.6);
font-size: 11px;
-moz-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.6);
-webkit-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.6);
font-family: arial;
}
.google-visualization-tooltip div {
padding:5px;
}