I am using the render event to alter the positioning of of my x-axis labels on a highchart. It works great - centering labels between ticks on a datetime x-axis and removing the last label.
When I export the chart - with the same setup - the function is called (see centerTimelineLabels below), but it cannot access the rendered x-axis labels. Please see the images below showing the different x-axis labels in the DOM and as an exported PNG.
jsfiddle here: https://jsfiddle.net/SirMunchington/36xcbr7m/52/
Specifically, this.container inside of the function, is an empty wrapper on export... no children.
Is there a way to access and manipulate the x-axis labels in a highchart when exporting?
exporting: {
chartOptions: { // specific options for the exported image
chart: {
backgroundColor: '#ffffff',
events: {
render: centerTimelineLabels
}
}
},
...
var centerTimelineLabels = function() {
var labels = $('.highcharts-xaxis-labels span', this.container).sort(function(a, b) {
return +parseInt($(a).css('left')) - +parseInt($(b).css('left'));
});
$(labels).css('margin-left',
(parseInt($(labels.get(1)).css('left')) - (parseInt($(labels.get(0)).css('left')) + parseInt($(labels.get(1)).width()))) / 2
);
$(labels.get(this.xAxis[0].tickPositions.length - 1)).remove();
};
CORRECT X-AXIS VIA WEB
INCORRECT X-AXIS VIA EXPORT
Thank you for the demo.
Try to use this config - notice that the render event triggers after each chart redraw:
"events": {
render() {
let chart = this,
xAxis = chart.xAxis[0],
ticks = xAxis.ticks,
firstTick = ticks[xAxis.tickPositions[0]],
secondTick = ticks[xAxis.tickPositions[1]],
ticksDistance = secondTick.mark.getBBox().x - firstTick.mark.getBBox().x;
for (let i in ticks) {
let tick = ticks[i];
if (!tick.isLast) {
tick.label.translate(ticksDistance / 2, 0)
}
}
}
}
Demo: https://jsfiddle.net/BlackLabel/o06r1yfw/
To hide the last label set the xAxis.showLastLabel property to false.
API: https://api.highcharts.com/highcharts/xAxis.showLastLabel
Related
I am running into an issue of incorrect point's tooltip on synchronised charts. On the synchronised charts the crosshair is shown and using ordinal:false I am plotting equidistance ticks.
The issue occurs when the crosshair moves along with mouse-move and shows the nearest point's data on the tooltip.
The expected behaviour is: when there is no data, crosshair should be shown but not the tooltip.
here is an existing SO fiddle I found https://jsfiddle.net/jknipp/g3vr5v44/13/
To achieve the effect you need, just return false if window.isOutOfSync, instead of No data string here:
formatter: function(tooltip) {
var header,
s = [];
console.log(window.isOutOfSync);
if (window.isOutOfSync) {
console.log("don't show tooltip");
//return false;
console.log(this)
return false;
}
$.each(this.points, function(i, point) {
// check to see if the point is in the overall graph
//var overallChart = $("#total_success_rates").highcharts();
//console.log(overallChart);
var isSuccessRate = (point.series.name == 'Success');
if (header == null) {
var config = point.point.getLabelConfig();
header = tooltip.tooltipFooterHeaderFormatter(config);
}
s.push(formatSuccessRateToolTip(point.y, isSuccessRate));
// $("#" + point.series.name.toLowerCase() + "-rate").html(point.y + "%");
});
return header + s.reverse().join('<br>');
}
[EDIT]
Additionally, please call reflow() inside of the chart.events.load function on both charts, just like below:
chart: {
renderTo: container,
type: 'areaspline',
events: {
load() {
this.reflow()
}
},
height: '220',
spacingBottom: 20,
spacingTop: 20,
spacingLeft: 20,
spacingRight: 20
},
Live example: https://jsfiddle.net/27veyw1d/
I'm displaying the x-axis of my Highstock chart at the top of the chart area with xAxis: { opposite: true}.
However the tooltip continues to show the x-axis value at the bottom of the chart, see for example here http://jsfiddle.net/ckj7kf2y/
Is there any way I can change the positioning of this be at the top, close to the x-axis?
Bonus points if someone knows why the tooltip.positioner callback isn't called when tooltip: { split: true }
It's possible to wrap core code to add this feature like in this demo: http://jsfiddle.net/ygmbwxtx/
(function(H){
H.wrap(H.Tooltip.prototype, 'renderSplit', function (proceed) {
proceed.apply(this, [].slice.call(arguments, 1));
var tooltip = this,
topAxis = tooltip.options.topAxis,
axisTT = tooltip.tt,
top = tooltip.chart.plotTop;
if (topAxis) {
axisTT.attr({
y: top - axisTT.height,
anchorY: top + 10
});
}
});
}(Highcharts))
and in chart's options:
...
tooltip: {
split: true,
topAxis: true
...
Bonus: positioner is not used for split tooltip - split uses own logic for positioning
I have different high charts as shown below. I have more number of series in one graph and have only one series in other one, In this case in my actual screen graph portion of first graph is bigger than second one, so is it possible to keep graph height constant without considering number of series (legends which occupied height at bottom)?
As was mentioned in the comment, you grab maximum of charts' margin bottom and set it for the rest of the chart. It should be set on load event in the last chart.
function adjustLegend() {
var charts = Highcharts.charts;
var marginBottomMax = charts
.reduce((prevChart, currChart) => Math.max(prevChart.marginBottom, currChart.marginBottom));
charts.forEach(chart => {
if (chart.marginBottom < marginBottomMax) {
chart.update({
chart: {
marginBottom: marginBottomMax
}
});
}
});
}
chart: {
events: {
load: adjustLegend
}
},
example: http://jsfiddle.net/wsrtaq09/1/
If you know what should be the legend height, you can set legend.maxHeight.
legend: {
layout: 'vertical',
maxHeight: 50,
},
example: http://jsfiddle.net/wsrtaq09/2/
I have a stock chart with the fixed tooltip like the one shown in the stock tooltip positioner example. Now I want to add some flags on the series. Each flag's tooltip should be adjacent to the flag when it is "mouse over", like the default positioning/format of a tooltip. Also, each flag's tooltip has its own text and should not affect the fixed tooltip when displayed (eg. the fixed tooltip would show the stock price and the flag tooltip would show some text associates with the flag)
Do you have any related sample code I can take a look at? thx!
This is not directly supported but possible to achieve, take a look: http://jsfiddle.net/hzYhQ/2/
1) Add custom property for a chart with mouseout/mouseover events for flags:
plotOptions: {
flags: {
events: {
mouseOver: function(){
this.chart.flagTooltip = true;
},
mouseOut: function(){
this.chart.flagTooltip = false;
}
}
}
}
2) Add checking where tooltip should be displayed according to that flag:
positioner: function (w,h,p) {
var x = 10,
y = 35;
if(this.chart.flagTooltip) {
x = p.plotX;
y = p.plotY;
}
return { x: x, y: y };
}
I'm working with Highchart.
I've got a multiple series graph in which each series have their own y-axis.
pretty much like this one (jsfiddle)
when we click on the legend item for a series, it hides it and the associated y-axis
(using showEmpty:false helped hiding also the name of the axes)
What I'm trying to achieve is hiding the y-Axis of a given series without hiding the series itself.
I tried to hide it by modifying the showAxis property like this :
serie.yAxis.showAxis = false;
but it doesn't work.
Anyone knows how I should do ?
EDIT : I managed to edit the text so I can remove the axis title by setting the text to null but its not enough to hide the whole axis and its values.
here's what i did to edit the text:
serie.yAxis.axisTitle.attr({
text: null
});
Highcharts 4.1.9+
Since 4.1.9, there is an option Axis.visible which can be used to show/hide an axis, demo: http://jsfiddle.net/3sembmfo/36/
Older versions of Highcharts
It's a new feature for Highcharts 3.0 - that allows to update axes in realtime: chart.yAxis[0].update(object) - as object takes the same options as for creating chart. For example:
chart.yAxis[0].update({
labels: {
enabled: false
},
title: {
text: null
}
});
And jsFiddle: http://jsfiddle.net/39xBU/2/
EDIT:
Use below snippet to hide/show axis by just calling axis.hide() and axis.show(). Live demo: http://jsfiddle.net/39xBU/183/
(function (HC) {
var UNDEFINED;
HC.wrap(HC.Axis.prototype, 'render', function (p) {
if (typeof this.visible === 'undefined') {
this.visible = true;
}
if(this.visible) {
this.min = this.prevMin || this.min;
this.max = this.prevMax || this.max;
} else {
this.prevMin = this.min;
this.prevMax = this.max;
this.min = UNDEFINED;
this.max = UNDEFINED;
}
this.hasData = this.visible;
p.call(this);
});
HC.Axis.prototype.hide = function () {
this.visible = false;
this.render();
HC.each(this.plotLinesAndBands, function (plotLine) {
plotLine.render();
});
};
HC.Axis.prototype.show = function () {
this.visible = true;
this.render();
HC.each(this.plotLinesAndBands, function (plotLine) {
plotLine.render();
});
};
})(Highcharts);
It's actually gotten simpler. You only have to set the yAxis title attribute to false:
yAxis: {
title: false
},
Here is an example: jsfiddle example
We can hide Yaxis label without hiding the y-Axis without hiding the series by returning the empty string as follows:
yAxis: {
title: '',
labels: {
formatter: function() {
return '';
},
style: {
color: '#4572A7'
}
}
},
For newer versions (I'm using the 6.2.0), the yAxis property has a parameter called gridLineWidth. Just set it to 0 and the grids for that axis are going to disappear. In this JSFiddle there is an example of it.
However, if you are in styled mode this it's trickier. Here, you have to set a className for the target axis and then set the CSS like this:
.highcharts-yaxis-grid {
&.right-axis {
path {
stroke: none;
}
}
}
For example, this will make dissapear the grids of the axis with a className set as right-axis. This allow to have different styles for the multiple axis.