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

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

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

highcharts - custom legend width

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>

How to display hovered point value in Highcharts Crosshair

As shown in screenshot I need my crosshair to move across the points but the tooltip value is snap to next value even the crosshair is not reached that point.I am facing an issue in highcharts. I want when I hover around the chart then crosshair should reflect the value of current point which is being hovered. As shown in code currently its changing values in mid way which is not reflecting right value as respect to crosshair.
Highcharts.chart('container', {
tooltip: {
snap: -1,
crosshairs: true
},
xAxis:{
crosshair: {
interpolate: true,
color: 'gray',
snap: false
},
},
plotOptions: {
line: {
marker: {
enabled: false
}
},
},
series: [{
marker: {
states: {
hover: {
enabled: false
}
}
},
step:'left',
data: [0, 1, 0, 1, 0, 1, 0]
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px"></div>
It's because you set the xAxis.crosschair.snap equal to false. Actually, you can remove the snap: false definition, because it's set to true by default. Then it should behave just like you want.
[EDIT]
If you would like to show current crosschairs xAxis value, it's not implemented in Highcharts, but Highstock has its own xAxis.crosschair.label property which serves the feature you need. Here is the example and documentation:
http://jsfiddle.net/hzcuf68y/
https://api.highcharts.com/highstock/xAxis.crosshair.label
If you don't want to change the Highcharts for Highstock, you can refer to this demo, where the crosschairs and labels are rendered manually: http://jsfiddle.net/mr1c03ae/
Live example: https://jsfiddle.net/n7bawfcg/
API Reference: https://api.highcharts.com/highcharts/xAxis.crosshair.snap
After alot of research I got the solution just posting here if someone may face the same problem. http://jsfiddle.net/F4e2Y/70/
function interpolate(data) {
var resolution = 0.1,
interpolatedData = [];
data.forEach(function(point, i) {
var x;
if (i > 0) {
for (x = data[i - 1].x + resolution; x < point.x; x += resolution) {
interpolatedData.push({
x: Highcharts.correctFloat(x),
y: Highcharts.correctFloat(data[i - 1].y),
});
}
}
interpolatedData.push(point)
});
return interpolatedData;
}
var data = [{
x: 0,
y: 1
}, {
x: 2,
y: 0
}, {
x: 4,
y: 1
}, {
x: 6,
y: 1
}, {
x: 8,
y: 0
}, {
x: 10,
y: 1
}];
Highcharts.chart('container', {
chart:{
zoomType: 'x',
},
tooltip: {
shared: true
},
xAxis: {
crosshair: true
},
series: [{
step:'left',
data: interpolate(data),
}]
});
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 300px; height: 300px; margin: 1em"></div>

how to add extra labels at load event in highcharts

Code is as below
chart: {
type: "funnel",
marginBottom: 25,
backgroundColor: "transparent",
events: {
load: function() {
var chart = this;
Highcharts.each(chart.series[0].data, function(p, i) {
chart.options.labels.items.push({
html: "less confident" + i,
style: { left: 550, top: 50 }
});
p.dataLabel.attr({
x: (chart.plotWidth - chart.plotLeft) / 2,
"text-anchor": "middle"
});
});
}
}
},
I see that you're trying to add a label for every point. Highcharts has build in functionality for this called data labels: https://api.highcharts.com/highcharts/series.line.dataLabels
Another approach is to use SVGRenderer.label: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#label

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