I have a stacked column/scatter chart with some dataLabels off to one side. The issue I am facing is that when my two markers begin to get close to one another, their dataLabels overlap
I need to always show both labels, so is there a way to detect when labels are overlapping and move the bottom one down by adjusting its y value based on how much overlap there is?
sample fiddle of the issue
Highcharts.chart('container', {
chart: {
type: 'column',
width: 500
},
title: {
text: 'Stacked column chart'
},
xAxis: {
visible: false,
},
yAxis: {
min: 0,
visible: false,
title: {
},
},
legend: {
layout:"vertical",
align: "right",
verticalAlign: "bottom",
itemMarginTop: 15,
y: -10,
x: -50
},
tooltip: {
enabled: false,
},
plotOptions: {
scatter: {
marker: {
symbol: "triangle",
},
dataLabels: {
enabled: true,
x: -80,
y: 50,
allowOverlap: true,
useHTML: true,
}
},
column: {
pointWidth: 70,
stacking: 'normal',
dataLabels: {
enabled: false
}
}
},
series: [{
name: '',
data: [100],
color: "#ededed"
}, {
name: '',
data: [500]
}, {
name: '',
data: [400]
},
{
type: "scatter",
data: [1000],
color: "#000",
dataLabels: {
formatter: function(){
return "<div class='label-text'>Your goal of <br/>$"+ this.y +"<br/>text</div>"
},
}
},
{
type: "scatter",
data: [900],
color: "#000",
dataLabels: {
formatter: function(){
return "<div class='label-text'>You are here <br/>$"+ this.y +"<br/>text</div>"
},
}
}]
});
You can correct data-labels positions by using the attr method on their SVG elements.
For example:
chart: {
events: {
render: function() {
const series = this.series;
const dl1 = series[3].points[0].dataLabel;
const dl2 = series[4].points[0].dataLabel;
if (dl1.y + dl1.height > dl2.y) {
dl2.attr({
y: dl1.y + dl1.height
});
}
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/5Lmh4owb/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.SVGElement.html#attr
https://api.highcharts.com/highcharts/chart.events.render
Related
I'm newbie to highchart and I've got a demo for polar chart using highcharts
Highcharts.chart('container', {
chart: {
polar: true,
type: 'area'
},
accessibility: {
description: 'ASDFR'
},
title: {
text: '',
x: -120
},
pane: {
size: '100%',
startAngle:-42
},
xAxis: {
categories: ['ATT', 'TEC', 'TAC', 'DEF', 'CRE'],
tickmarkPlacement: 'on',
lineWidth: 0,
labels:{
formatter: function(){
return this.value + '???'
}
}
},
yAxis: {
gridLineInterpolation: 'polygon',
},
tooltip: {
shared: true,
pointFormat: '<span style="color:{series.color}">{series.name} <b>{point.y:,.0f}</b></span>'
},
legend: {
align: 'right',
verticalAlign: 'middle',
layout: 'vertical'
},
series: [{
name: '',
data: [73, 80, 80, 54, 92],
}],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
align: 'center',
verticalAlign: 'bottom',
layout: 'horizontal'
},
pane: {
size: '70%'
}
}
}]
}
});
How can I show the value of the series right in the xAxis label e.g ATT 73, TEC 80, TAC 80...
You can get the associated value through series data. Example:
xAxis: {
...,
labels: {
formatter: function() {
return this.value + ' ' + this.chart.series[0].yData[this.pos];
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/pyohzk8c/
API Reference: https://api.highcharts.com/highcharts/xAxis.labels.formatter
I have the following chart and I would like to increase the distance between y axis labels and the chart (light blue lines) - check the image, more distance between 10k and the blue lines
In y axis I tried to combine the settings of yAxis offset, yAxis labels padding and yAxis title margin, but no success
How do I achieve this?
These are the settings of the chart
options: {
chart: {
updateArgs: [false, false, true],
borderWidth: 1,
marginLeft: 40,
marginRight: 2,
type:'line',
zoomType: 'x',
animation: false,
height:250,
title: {
text: ''
},
panning:true
},
title: {
text: ''
},
time:{
useUTC:true
},
credits:{
enabled:false
},
tooltip: {
shared: true,
formatter: this.tooltipFormatter
},
title:{
text:null
},
lang: {
noData: 'loading...'
},
rangeSelector: {
inputEnabled: false
},
xAxis:{
type:'datetime',
max:this.maxdate,
min:this.mindate,
title:
{
align:'high'
},
labels: {
padding: 50,
format: '{value:%H:%M}',
style: {
fontSize: '10px'
}
},
crosshair: {
enabled: true,
width: 1,
color: '#000'
},
events : {
afterSetExtremes : this.afterSetExtremes
}
},
yAxis: {
title: {
text: this.streamChart.title + ' [' + this.streamChart.unit+']',
margin:20,
fontSize:"15px"
},
labels: {
step: 2,
staggerLines: 2,
enabled:true,
align: 'left',
padding:0
},
alignTicks:'left',
textAlign:'left',
align:'middle',
opposite:false,
offset:0
},
plotOptions: {
series: {
animation: false,
boostThreshold: 1,
pointInterval: 3600 * 1000
}
},
legend: {
enabled: false
},
responsive: {
rules: [{
condition: {
maxWidth: '100%',
minHeight: 300
},
chartOptions: {
subtitle: {
text: null
},
navigator: {
enabled: false
},
legend: {
enabled: false
},
yAxis: {
title: {
enabled: false
}
}
}
}]
}
,series: [{
name:this.streamChart.title,
id:this.streamChart.id,
data:[]
}],
},
Increase chart.marginLeft and enable reserveSpace or align labels by x property:
labels: {
...,
reserveSpace: true
}
Live demo: http://jsfiddle.net/BlackLabel/71gxj4sd/
API Reference:
https://api.highcharts.com/highcharts/yAxis.labels.reserveSpace
https://api.highcharts.com/highcharts/yAxis.labels.x
Playing with the Highcharts Map samples and wanted to see how multiple series worked with maps. Here is the US population density map with another series showing the state capitals:
$.getJSON('https://cdn.rawgit.com/highcharts/highcharts/057b672172ccc6c08fe7dbb27fc17ebca3f5b770/samples/data/us-capitals.json', function (dcap) {
$.getJSON('https://cdn.rawgit.com/highcharts/highcharts/057b672172ccc6c08fe7dbb27fc17ebca3f5b770/samples/data/us-population-density.json', function (data) {
// Make codes uppercase to match the map data
$.each(data, function () {
this.code = this.code.toUpperCase();
});
if (_dochartwhenready === true) {
if (_domap === true) {
var mapobject = {
chart: {
map: 'countries/us/us-all',
borderWidth: 1,
renderTo: 'container'
},
title: {
text: 'US population density (/km²)'
},
exporting: {
sourceWidth: 600,
sourceHeight: 500
},
legend: {
layout: 'horizontal',
borderWidth: 0,
backgroundColor: 'rgba(255,255,255,0.85)',
floating: true,
verticalAlign: 'top',
y: 25
},
mapNavigation: {
enabled: true
},
colorAxis: {
min: 1,
type: 'logarithmic',
minColor: '#EEEEFF',
maxColor: '#000022',
stops: [
[0, '#EFEFFF'],
[0.67, '#4444FF'],
[1, '#000022']
]
},
series: [{
animation: {
duration: 1000
},
data: data,
joinBy: ['postal-code', 'code'],
dataLabels: {
enabled: true,
color: '#FFFFFF',
format: '{point.code}'
},
name: 'Population density',
tooltip: {
pointFormat: '{point.code}: {point.value}/km²'
}
},
{
animation: {
duration: 3000
},
type: 'mappoint',
name: 'Cities',
color: Highcharts.getOptions().colors[1],
data: dcap,
joinBy: ['lat', 'lat', 'lon', 'lon'],
dataLabels: {
enabled:true,
color: '#ccccc',
format: '{point.capital}'
},
tooltip: {
pointFormat: '{point.capital}: {point.population}'
}
}]
};
_map = new Highcharts.Map(mapobject);
}
This works -- partly:
The tool tips work exactly as expected. However, only a few state capital names show up on the map. How come?
The source of the problem are overlapping data labels. This code forces Highcharts to show all of them:
plotOptions: {
series: {
dataLabels: {
allowOverlap: true
}
}
},
Live demo: https://jsfiddle.net/BlackLabel/vtwv061b/
API reference: https://api.highcharts.com/highmaps/plotOptions.series.dataLabels.allowOverlap
This is simply due the zoom level, aparently.
Also, I would not recomend using joinBy on lat and long since the may vary in really small decimals.
Here's a fiddle with a working example: https://jsfiddle.net/3ttmyxmo/
If you zoom in you will see the capital names popping over.
I used joinBy on postal-code and abrev instead of lat long:
{
animation: {
duration: 3000
},
type: 'mappoint',
name: 'Cities',
color: Highcharts.getOptions().colors[1],
data: capitals,
joinBy: ['postal-code', 'abrev'],
dataLabels: {
enabled:true,
color: '#ccccc',
format: '{point.capital}'
},
tooltip: {
pointFormat: '{point.capital}: {point.population}'
}
}
In an Angular 4 project I am using the angular2-highcharts library to create a stacked bar chart. The following object is the configuration I have so far.
{
title: { text: '' },
xAxis: {
categories: [''],
crosshair: true,
visible: false
},
yAxis: {
min: 0,
max: 100,
title: {
text: ''
},
labels: {
enabled: true
},
visible: false
},
chart: {
type: 'bar',
backgroundColor: 'rgba(255, 255, 255, 0.1)'
},
legend: {
enabled: false
},
plotOptions: {
column: {
pointPadding: 0,
borderWidth: 0,
stacking: 'normal',
dataLabels: {
enabled: true,
formatter: function() {
return this.point.y + '%';
},
inside: true
},
enableMouseTracking: false,
},
series: {
stacking: 'normal',
dataLabels: {
enabled: true,
formatter: function () {
if (this.point.y) {
return this.point.y + '%';
}
return '';
},
style: { fontSize: '10px' },
padding: 10
},
borderWidth: 0
}
},
series: [{
name: 'Pending',
data: ...,
color: '#ff4233'
}, {
name: 'Executed',
data: ...,
color: '#34d788'
}, {
name: 'Cancelled',
data: ...,
color: '#8f8c87'
}]
}
and this produces this visual result ->
I need to transform this into ->
As you see in the desired result the chart has more height and also its edges are round. That I don't know how to do.
Have you tried to use rounded-corners plugin? With it you can use following properties:
borderRadiusTopLeft, borderRadiusTopRight, borderRadiusBottomRight and borderRadiusBottomLeft
Plugin Reference:
https://github.com/highcharts/rounded-corners
Example:
http://jsfiddle.net/3Lhzx8ao/
I have a highchart, as showed on the appended image.
I am attempting to format the legend of only my last data stacked. In this case, index 1 always.
Any help on how to achieve this?
My main goal, being, on there always showing a value i have in a variable, which will be the max value possible.
createChart: function (id, chartData, maxYValues, chartTitle, chartNames, dataToMax) {
var me = this;
debugger;
me.highChart = new Highcharts.Chart({
chart: {
type: 'column',
renderTo: id
},
title: {
text: chartTitle,
fontSize: '8px'
},
xAxis: {
labels: {
overflow: 'justify'
},
categories: chartNames
},
yAxis: {
gridLineWidth: 0,
minorGridLineWidth: 0,
labels: {
enabled: false
},
stackLabels: {
enabled: true,
format: maxYValues
},
title: {
enabled: false
}
},
colors: ['#afafaf', '#f89c1c', '#3aaa80'],
credits: {
enabled: false
},
tooltip: {
pointFormat: '<span>{point.name}</span>'
},
plotOptions: {
series: {
colors: ['#3aab80', '#3aab80'],
colorByPoint: true,
borderWidth: 0,
dataLabels: {
enabled: true,
headerFormat: '{point.y + point.name}',
format: '{y} mb',
verticalAlign: 'top',
y: -20
}
},
column: {
stacking: "percent"
},
area: {
dataLabels: {
enabled: false
}
}
},
legend: {
labelFormat: '<b>{point.y} MB</b><br/>',
labelFormatter: function () {
if (me.series.data.index === 1) {
return maxYValues;
}
}
},
series: [{
showInLegend: false,
data: chartData,
color: '#3aab80'
}, {
showInLegend: false,
data: dataToMax,
legend: {
labelFormat: maxYValues + 'MB</b><br/>'
}
}],
navigation: {
menuItemStyle: {
fontSize: '8px'
}
}
});
},
Thank you
UPDATE: Added code snipped, and updated the image to what my current code is showing