xAxis - point specific label positions - highcharts

Is there a way to have a point specific positionning of the xAxis labels ?
I am using a waterfall chart and for some bars I would like the label to appear directly under the bar like below :
I have found the following code in the xAxis plotOptions but at this point I don't see how I can acces the info on the bottom of the chart.
xAxis: {
labels: {
y:-100 //label's y position
}
},

You can use point dataLabels to achieve such result:
dataLabels: {
crop: false,
overflow: 'none',
verticalAlign: 'bottom',
format: 'label1',
y: 20
}
Live demo: https://jsfiddle.net/BlackLabel/71jtp5mf/
API Reference: https://api.highcharts.com/highcharts/series.waterfall.dataLabels
Another way is to create your own custom function to position the xAxis labels, for example:
events: {
load: function() {
var chart = this,
point;
Highcharts.objectEach(chart.xAxis[0].ticks, function(tick) {
if (!tick.isNewLabel) {
point = chart.series[0].points[tick.pos];
tick.label.attr({
y: point.plotY + chart.plotTop + point.shapeArgs.height + 15
})
}
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/oaj9bgt4/

Related

Highcharts draw grid lines into yAxis area

In Highcharts, there is a possibility to shift the y-Axis labels into the plot-area with
yAxis: {
labels: {
align: 'left',
x: 0,
y: -2
}
}
With this setting, the labels are covered by the lines, data-labels and so on.
Is it possible to draw the horizontal grid lines across the yAxis-Label-Area without making the xAxis and the series start there. The wished behavior is indicated with the black lines in the image below.
The simplest solution is to adjust the xAxis, for example:
xAxis: {
min: -0.5
}
Live demo: http://jsfiddle.net/BlackLabel/qnayxb04/
API: https://api.highcharts.com/highcharts/xAxis.min
If you want to have more control over the lines, you can use setAttribute to edit the path element:
chart: {
events: {
load: function() {
var gridLines = this.yAxis[0].gridGroup.element.children,
i,
path;
for (i = 0; i < gridLines.length; i++) {
path = gridLines[i].attributes.d.nodeValue;
path = 'M 40' + path.substr(4);
gridLines[i].setAttribute('d', path)
}
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/61h5qtn9/1/

Show plotlines in highcharts with hidden axis?

Is there a way to show plotlines even when the associated axis has visible: false? Is seems that hiding the axis also hides the plotlines.
More details...
I'm drawing a diagram of a day, like this:
I simply want to add a vertical line at certain times, line the "Now" time, etc.
If I do that using a plot line, then the axis shows up too:
I definitely do not want the axis to show.
My plan now is to draw my own line on the chart using render.rect or render.path. Is there another option?
I found a relatively trivial solution... just hide it with css:
.highcharts-xaxis {
display: none;
}
and in js:
xAxis: {
type: 'datetime',
labels:{
enabled: false
}
}
You can extend Highcharts by wrapping the method responsible for redrawing an axis.
Highcharts.wrap(Highcharts.Axis.prototype, 'redraw', function(p) {
p.call(this);
console.log(this);
var axis = this,
each = Highcharts.each,
options = this.options;
// move plot lines and bands
if (!axis._addedPlotLB) { // only first time
each((options.plotLines || []), function(plotLineOptions) {
axis.addPlotBandOrLine(plotLineOptions);
});
axis._addedPlotLB = true;
}
each(this.plotLinesAndBands, function(plotLine) {
plotLine.render();
});
});
example: http://jsfiddle.net/ncs81btt/
The solution above is not very elegant, though. Much better ways to do it is using Renderer or hide particular axis elements (labels, ticks, etc.).
Depending on what you need from plot lines functionality, using renderer requires to do some calculations.
var customPlotLines = [{
value: 5,
color: 'red',
width: 3
}, {
value: 10,
color: 'yellow',
width: 3
}]
function renderPlotLines() {
var axis = this.xAxis[0],
top = axis.chart.plotTop,
bottom = top + axis.chart.plotHeight,
path = [
'M', null, top,
'L', null, bottom
];
if (!this.customPlotLines) {
this.customPlotLines = customPlotLines.map(plotLine => {
return this.renderer.path([]).add();
});
}
this.customPlotLines.forEach((plotLine, i) => {
var opt = customPlotLines[i];
path[4] = path[1] = axis.toPixels(opt.value);
plotLine.attr({
d: path.join(' '),
'stroke-width': opt.width,
stroke: opt.color
});
});
}
Hook into load/redraw event, so the elements will resize.
chart: {
zoomType: 'xy',
events: {
load: renderPlotLines,
redraw: renderPlotLines
}
},
example: http://jsfiddle.net/ncs81btt/1/

How do I move the title-label of a polar (spider) graph with HighChart 4?

I created a polar graph. It has some complicated title-lables. It looks as expected on desktop:
But when it's on mobile, the title-lables don't have enough room to show up. And HighCharts neither did it for me. So it looks like this:
What I desire is to move the two title-labels under the triangle, without changing how it behaves in Desktop view.
What can I do to achieve this?
Thanks!
You can translate labels using tick.label.attr({ x: new_x }); method. For example, create some reposition method:
function reposition () {
var chart = this,
xAxis = chart.xAxis[0],
tick, bbox, xy;
$.each(xAxis.tickPositions, function(i, pos){
tick = xAxis.ticks[pos];
if (tick && tick.label) {
bbox = tick.label.getBBox(); // get label's bounding box
xy = tick.label.xy; // get label's xy position
if (xy.x - bbox.width < 0) {
tick.label.attr({
x: bbox.width
});
}
if (xy.x + bbox.width > chart.plotWidth + chart.plotLeft) {
tick.label.attr({
x: chart.plotWidth + chart.plotLeft - bbox.width
});
}
}
});
}
Which will be called on each chart redraw and starting load events:
$('#container').highcharts({
chart: {
polar: true,
type: 'line',
events: {
redraw: reposition,
load: reposition
}
},
...
});
Live demo: http://jsfiddle.net/wmgbbp9k/

verticalAlign ignored for non 0 rotation

If I try to rotate the data labels in my column charts, I can not align the labels at the bottom of my columns, verticalAlign appears to be completed ignored.
basically trying to use:
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
verticalAlign: 'bottom',
rotation: -90
}
}
}
fiddle with it at: http://jsfiddle.net/FbhAs/
Anyone know a work-around?
-= Jab
The dataLabels don't seem to align correctly to the bottom. Instead, use the axis labels themselves. For a column chart, you would put this in xAxis for the chart options.
xAxis: {
labels: {
enabled: true,
rotation: -90,
y: -10 // negative goes upwards
}
}
You can then add styling, a formatter function, etc. as per dataLabels.
You can update datalabels position, based on translate() function which allows to "move" svg object for defined postiison.
http://jsfiddle.net/wMLg6/37/
var bottom = chart.plotHeight - 20;
$.each(chart.series[0].data,function(i,data){
data.dataLabel.attr({
y: bottom
});
});

Highcharts - labels inside and outside a pie chart

I know it's possible to put pie chart labels either inside or outside the pie by changing plotOptions.pie.dataLabels.distance. I am trying to figure out whether it's possible to change that on a point by point basis:
if slice is smaller than 15%, place labels inside the slice
else place the label outside the slice
Is this possible in Highcharts? Below is one of my attempts, which doesn't work; the plain jsfiddle is here: http://jsfiddle.net/supertrue/q6bQP/
plotOptions: {
pie: {
dataLabels: {
distance: -30,
color: 'white',
formatter: function() {
if (this.y < 15 ) {
this.point.dataLabels.color = 'red';
this.point.dataLabels.distance = 20;
return this.point.name;
} else {
return this.point.name;
}
}
},
This post can helps you to acomplish your work :
Is it possible to position Highcharts dataLabels depending on the value?
$.each(chart.series[0].data, function(i, point) {
// using the value or calculating the percent
if(point.percentage < 30) {
point.dataLabel.attr({y:20});
}
});
This can be achieve using events as well.
Working fiddle : Outside Fiddle
Here if data point is less than five the show labels outside the charts.
chart: {
type: 'pie',
events: {
load: function() {
var series = this.series[0];
setTimeout(function(){
(series.points).forEach(function(point, i){
if (point.y < 5) {
point.update({dataLabels:{distance: 2}});
}
});
}, 200);
}
}
}

Resources