I am trying to find a way to control width of the x-axis labels container in bar charts in styled mode. I want to have preset values and depending on the preset have labels to take 20, 30, 40, 50% of the graphic. Is there a property for that?
Thank you!
If you want to set labels' width depending on their length and relative to chart width, you can use chart.event.render to achieve that. It will allow you to find the number of characters and set dynamically the percentage width.
var allowChartUpdate = true;
Highcharts.chart('container', {
chart: {
type: 'bar',
styledMode: true,
events: {
render: function() {
if (allowChartUpdate) {
this.xAxis[0].categories.forEach(category => {
if (category.length > 10) {
var dynamicMargin = this.chartWidth * 50 / 100;
allowChartUpdate = false;
this.update({
chart: {
marginLeft: dynamicMargin
}
}, true, true, false);
allowChartUpdate = true;
}
})
}
}
}
},
...
Demo:
https://jsfiddle.net/BlackLabel/59xjq4du/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
Related
How would I go about and make custom image and text for an axis tick in highcharts.js? I need a normal number as label for the tick and then a small colored square image (dependant on another variable from a special array of values) displayed below the number? This is what I need to do, see image below
You can create an additional HTML element for rectangles and in 'load' event use color-axis to translate values into background colors.
const colorValues = [5, 9, 14, 15, 1, 4];
Highcharts.chart('container', {
...,
chart: {
events: {
load: function() {
const rectangles = document.getElementsByClassName('label-rect'),
colorAxis = this.colorAxis[0];
[].forEach.call(rectangles, function(rect) {
rect.style.backgroundColor = colorAxis.toColor(rect.dataset.value);
});
}
}
},
xAxis: {
type: 'category',
labels: {
style: {
'text-align': 'center'
},
useHTML: true,
formatter: function() {
return this.pos + '<br/>' +
'<span data-value="' + colorValues[this.pos] +
'" class="label-rect"></span>'
}
}
}
});
Live demo: http://jsfiddle.net/BlackLabel/7146g2r3/
API Reference:
https://api.highcharts.com/highcharts/xAxis.labels
https://api.highcharts.com/highcharts/colorAxis
I try to create a pie chart with the halo effect. This works on hover but not on select. Is this possible?
Because we want to keep our selected item visible without slicing it out... So we want to show our selected slice with the halo effect but can't find if this is possible
Highcharts doesn't provide such a functionality out of the box. However, you can achieve it by adding your custom code in point click event callback. There you can render a halo effect using Highcharts renderer.path() method. Check the demo and code posted below and do not hesitate to ask me any question if something is unclear for you.
Code:
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie',
events: {
load: function() {
var chart = this;
chart.customHalo = {
graphic: null,
index: null
}
}
}
}
...
series: [{
...
point: {
events: {
click: function() {
var point = this,
chart = point.series.chart,
shapeArgs = point.shapeArgs,
size = 10,
opacity = 0.5,
path = chart.renderer
.symbols
.arc(
shapeArgs.x + chart.plotLeft,
shapeArgs.y + chart.plotTop,
shapeArgs.r + size,
shapeArgs.r + size, {
innerR: shapeArgs.r - 1,
start: shapeArgs.start,
end: shapeArgs.end
}
),
drawNewGraphic = false,
arc;
drawNewGraphic = (chart.customHalo.index !== point.index) ? true : false;
if (!drawNewGraphic && chart.customHalo.graphic) {
chart.customHalo.graphic.destroy();
chart.customHalo.index = null;
chart.customHalo.graphic = null;
} else if (chart.customHalo.graphic) {
chart.customHalo.graphic.destroy();
}
if (drawNewGraphic) {
arc = chart.renderer
.path(path)
.attr({
fill: point.color,
opacity: opacity
}).add();
chart.customHalo = {
index: point.index,
graphic: arc
}
chart.customHalo.index = point.index;
}
}
}
},
...
}]
Demo:
https://jsfiddle.net/BlackLabel/59hyq14v/
API reference:
https://api.highcharts.com/highcharts/chart.events.load
https://api.highcharts.com/highcharts/series.pie.point.events.click
I have a highcharts column chart, here is the jsFiddle for it. I want to keep the space between the series as it is -- really close to each other without touching. But I'd like to increase the space between the categories so that it's more distinguishable they are different categories. I've tried playing around with pointpadding and grouppadding but everything I've tried wants to increase/decrease the space between all the columns. Any ideas?
plotOptions: {
column: {
borderRadius: 5,
dataLabels: {
enabled: true,
},
groupPadding: 0,
pointWidth: 45,
},
},
In Highcharts API we can read:
pointWidth: number
A pixel value specifying a fixed width for each column or bar. When
null, the width is calculated from the pointPadding and groupPadding.
Defaults to undefined.
So in this situation pointPadding and groupPadding can be not respected but you can create your own function for positioning the columns, for example:
events: {
render: function() {
var series = this.series;
if (redrawEnabled) {
if (this.chartWidth > 600) {
if (this.options.plotOptions.column.grouping) {
redrawEnabled = false;
this.update({
plotOptions: {
column: {
grouping: false
}
}
});
redrawEnabled = true;
}
series.forEach(function(s, i) {
s.points.forEach(function(p) {
if (i === 0) {
p.graphic.attr({
translateX: 25
});
p.dataLabel.attr({
translateX: p.dataLabel.translateX + 25
});
} else {
p.graphic.attr({
translateX: -25
});
p.dataLabel.attr({
translateX: p.dataLabel.translateX - 25
});
}
});
});
} else {
if (!this.options.plotOptions.column.grouping) {
redrawEnabled = false;
this.update({
plotOptions: {
column: {
grouping: true
}
}
});
redrawEnabled = true;
}
}
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/hvqs4juy/
How can I hide a stackLabel (a label above the column) in highCharts when the text in the label is bigger than the column (As you can see in the image below).
I want to show empty string when my data exceeds the column width.
This is part of the code which is responsible for showing the data:
yAxis: {
stackLabels: {
style: {
color: 'black'
},
enabled: true
formatter: function () {
return this.total + " mm ";
}
}
}
Create a function which loop through the stack labels and compare their width with the point's width - according to the comparison hide or show the label.
Function can look like this:
function hideLabel() {
const axis = this.yAxis[0];
const stacks = axis.stacks.column;
const pointWidth = this.series[0].points[0].shapeArgs.width;
Object.keys(stacks).forEach(key => {
const label = stacks[key].label;
label.attr({
visibility: label.getBBox().width > pointWidth ? 'hidden' : 'visible'
});
})
}
Set this function on load and redraw events:
chart: {
type: 'column',
events: {
load: hideLabel,
redraw: hideLabel
}
},
example: http://jsfiddle.net/nq5ke47z/
Is there way to set the label of an Bar Chart to 50% of the charts width? I've tried this but it does not work:
xAxis: {
categories: [],
labels: {
formatter: function() {
var text = this.value;
return '<div class="js-ellipse" style="width:100%; overflow:hidden; text-overflow: ellipsis" title="' + text + '">' + text + '</div>';
},
style: {
width: '50%'
},
useHTML: true
}
},
So goal is to have labels on the left side of the bar chart that are 50% of the width of the whole chart container.
You have an option for that in the plotOptions :
plotOptions: {
bar: {
dataLabels: {
enabled: true,
inside: true
// ^^^^^^^^^^^^
}
}
},
The property inside :
For points with an extent, like columns, whether to align the data label inside the box or to the actual value point. Defaults to false in most cases, true in stacked columns.
And an example forked from the official documentation : http://jsfiddle.net/XXB9k/
EDIT :
There is another option to center the x labels (I don't know witch labels your are talking about), but there is a solution not far away from your code :
xAxis: {
...
labels: {
enabled: true,
x: this.width / 2,
}
}
An example : http://jsfiddle.net/QMPkh/
FINAL EDIT :
In fact you can simply use the width of the chart in the label formatter :
labels: {
enabled: true,
formatter: function() {
return '<div style="width:' + (this.axis.width/2) +'px">'+this.value+'</div>';
},
useHTML: true
}
An example to show the result : http://jsfiddle.net/QMPkh/2/
Unfortunately width in percent is not supported, only in pixels.