highcharts - custom legend width - highcharts

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>

Related

highcharts - exported png in horizontal bar charts

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

resize on load of highcharts in gridster widget

Found a couple of posts that came close to solving this. I'm loading a chart into a widget and it's not filling it, instead it's centered and extended past the widget - about only 1/3 of the pie chart shows for example.
I found the resize options for gridster and it gets me almost there... the same problem exists when I load the page, but when I resize the widget the chart fills it in perfectly.
I've tried aligning the chart, removing width and height settings, addeing resize and stop elements to gridsters..
var gridster = null;
$(document).ready(function () {
gridster = $(".gridster ul").gridster({
widget_base_dimensions: ['auto', 140],
autogenerate_stylesheet: true,
min_cols: 1,
max_cols: 6,
widget_margins: [5, 5],
resize: {
enabled: true,
resize: function (e, ui, $widget) {
Highcharts.charts[0].reflow(); // reflow the first chart...
},
stop: function(e, ui, $widget) {
Highcharts.charts[0].reflow(); // reflow the first chart...
}
}
}).data('gridster');
$('.gridster ul').css({'padding': '0'});
});
Highcharts.chart('container', {
chart: {
type: 'pie'
},
title: {
text: 'User data',
style: {"fontSize": "15px" , "color":"red"},
},
subtitle: {
text: 'Source: Click the slices to view categories.'
},
plotOptions: {
pie: {
showInLegend: false,
dataLabels: {
formatter: function(){
console.log(this);
if (this.percentage > 5)
return this.key + ': ' + this.y;
else
this.point.visible = false;
return '';
}
}
},
series: {
dataLabels: {
enabled: true,
}
}
},
tooltip: {
headerFormat: '<span style="font-size:11px">{series.name}</span><br>',
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
when page loads the pie chart is sized to fit into the gridster widget.
Add one div wrapper around widget and add class which having height and width of that widget. It will render your highchart graph in that wrapper only.
<div class="size-1x1">
Render your graph code here
</div>
CSS:
.size-1x1 {
height:100px;
width: 120px;
}

How to place ranking like top 10 and put x axis labels on right of horizontal bar chart?

Current Chart
xAxis: {
categories: ['Africa', 'America', 'Asia', 'Europe', 'Oceania'],
title: {
text: null
},
labels: {
x : 25,
align: 'left'
}
},
My Script in here
http://jsfiddle.net/puff0211/dtcLn8sm/14/
Desired Chart
Does anyone know to accomplish this?
Thank you!
One of the solutions here is to slightly change the position of both axes via left property (it's not documented but it works) and create additional labels using SVG Renderer. chart.events.load is a good place for it because when it launches ticks values and positions are already computed - we can use them to create additional labels:
load: function() {
var ticks = this.xAxis[0].ticks,
renderer = this.renderer;
for (var prop in ticks) {
var t = ticks[prop];
if (t.label) {
var coords = t.label.xy,
label = renderer.text(t.pos + 1, coords.x - additionLabelsOffset, coords.y).add();
}
}
}
(...)
xAxis: {
left: axesOffset
(...)
},
yAxis: {
left: axesOffset
(...)
}
Live demo: http://jsfiddle.net/kkulig/cq2otgr1/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
My solution is simple.
Let chart margin keep width with left lable.(api use chart.margin)
Allow X Axis can display 2 lable. (api use useHTML and formatter )
Code:
chart: {
type: 'bar',
margin: [ 0, 0, 70, 70]
},
{...},
xAxis: {
labels: {
x : 0,
align: 'left',
useHTML: true,
formatter: function() {
return '<div style="position: relative; top: 0px; right: 50px"> No. '+ (this.pos + 1) +'</div>\
<div style="position: absolute; top: 0px; left: 20px"><b>'+ this.value +'</div>';
}
}
Live demo: http://jsfiddle.net/puff0211/pv84nLub/
API Reference:
https://api.highcharts.com/highcharts/chart.margin
https://api.highcharts.com/highcharts/xAxis.labels.useHTML
https://api.highcharts.com/highcharts/xAxis.labels.formatter

Customise Highstock tooltip conditionally

I would like to make tooltip in Highstock styled differently(not just style of content, but style for tooltip itself. For example, different padding, shadow, border radious etc) when hovering over flag series and line serieses. However, it looks like these properties needs to be configured in the tooltip configuration object. Not sure if it can be dynamically changed.
Like in this jsbin:
http://jsbin.com/cixowuloxa/1/edit?js,output
What's the better way to give 'Summer arrives' tooltip different style than other shared tooltips?
Your approach is correct. In the formatter callback wrap the text in the html tags and style it using css, inline or by class name, depending if it is a flag or line series. Make sure you set useHTML to true.
tooltip: {
useHTML:true,
borderWidth: 0,
headerFormat: '',
shared: true,
formatter: function(){
if (!!this.points) {
return this.points
.reduce(
function(prev, cur) {
return prev +
'<br>' + cur.series.name + ': '+ cur.y;
}, '');
}
return "<div style='border:5px solid black; padding: 20px'>Summer arrives!</div>";
},
padding: 0
}
example: https://jsfiddle.net/hpeq7Lbe/1/
Actually, you can set different options for flag's and line's tooltip, but not all the options are supported, e.g. padding or border width will not work - they have to be set in the tooltip's global options.
plotOptions: {
line: {
tooltip: {
pointFormat: 'line',
borderWidth: 10, // not supported
padding: 10 // not supported
}
},
flags: {
tooltip: {
pointFormat: 'flags',
borderWidth: 1, //not supported
padding: 1 // not supported
}
}
}
example: https://jsfiddle.net/hpeq7Lbe/3/

Auto chart height

The default highstock chart has height = 400px.
How can height chart be set for auto size based on chart axis and its sizes ?
See the example bellow, the navigation bar is over the volume panel.
http://jsfiddle.net/BYNsJ/
I know that I can set the height for the div but I have a solution that insert/remove axis/series dynamically in the chart and would be nice an auto height chart.
The example is the same Candlestick/Volume demo from Highchart site, but without height property in the div container.
// split the data set into ohlc and volume
var ohlc = [],
volume = [],
dataLength = data.length;
for (i = 0; i < dataLength; i++) {
ohlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
])
}
// set the allowed units for data grouping
var groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]];
// create the chart
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Historical'
},
yAxis: [{
title: {
text: 'OHLC'
},
height: 200,
lineWidth: 2
}, {
title: {
text: 'Volume'
},
top: 300,
height: 100,
offset: 0,
lineWidth: 2
}],
series: [{
type: 'candlestick',
name: 'AAPL',
data: ohlc,
dataGrouping: {
units: groupingUnits
}
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
}
}]
});
});
});
Regards.
here is one example which is resize chart according screen.
http://jsfiddle.net/davide_vallicella/LuxFd/2/
Just don't set the height property in HighCharts and it will handle it dynamically for you so long as you set a height on the chart's containing element. It can be a fixed number or a even a percent if position is absolute.
http://api.highcharts.com/highcharts/chart.height
By default the height is calculated from the offset height of the containing element
find example here:- http://jsfiddle.net/wkkAd/149/
#container {
width:100%;
height:100%;
position:absolute;
}
hey I was using angular 2+ and highchart/highstock v.5, I think it will work in JS or jQuery also, here is a easy solution
HTML
<div id="container">
<chart type="StockChart" [options]="stockValueOptions"></chart>
</div>
CSS
#container{
height: 90%;
}
TS
this.stockValueOptions = {
chart: {
renderTo: 'container'
},
yAxis: [{
height: '60%'
},{
top: '65%',
height: '35%'
}]
}
Its working, and a easy one. Remove chart height add height in '%' for the yAxis.
Highcharts does not support dynamic height, you can achieve it by $(window).resize event:
$(window).resize(function()
{
chart.setSize(
$(document).width(),
$(document).height()/2,
false
);
});
See demo fiddle here.
You can set chart.height dynamically with chart.update method.
http://api.highcharts.com/highcharts/Chart.update
function resizeChartFromValues (chart) {
const pixelsForValue = 10
const axis = chart.yAxis[0]
chart.update({ chart: { height: (axis.max - axis.min) * pixelsForValue } })
}
const options = {
chart: {
events: {
load () {resizeChartFromValues(this)}
}
},
series: [{
data: [30, 70, 100],
}]
}
const chart = Highcharts.chart('container', options)
setTimeout(() => {
chart.series[0].setData([10, 20, 30])
resizeChartFromValues(chart)
}, 1000)
Live example: https://jsfiddle.net/a97fgsmc/
I had the same problem and I fixed it with:
<div id="container" style="width: 100%; height: 100%; position:absolute"></div>
No special options to the chart. The chart fits perfect to the browser even if I resize it.

Resources