I am building a pie chart where the labels for the data points can very greatly in length, the legend is configured to be vertical and positioned on the left side.
I have added a label element to the bottom of the chart that shows the total of all data points.
The problem I am facing is that the positioning of this label (via the style element) is based on how wide the legend is, which occasionally if the legend is wide enough will be pushed off the right side of the chart.
Does anyone know of a way that I can style this label so that is positioned based solely on the width of the entire chart.
Here is the styling applied to the label (I tried adding the position value but this didn't appear to do anything):
style: {
top: '325px',
position: 'absolute',
left: '-160px',
'font-size': '175%'
}
Here is an example of the chart that I'm working with, you can see that the value for the total has bee cut off.
EDIT:
As per Sebastian's comment I was able to effectively solve the issue by using the legend label formatter to limit the length of the series names. Here is the code:
labelFormatter: function () {
var formattedName = this.name;
if (formattedName.length > 17) {
formattedName = formattedName.substr(0, 14) + '...';
}
return formattedName;
}
Have you tried to use labelFormatter http://api.highcharts.com/highcharts#legend.labelFormatter ?
Related
Im trying to sync Highcharts horizontally, stacked with multiple charts vertically- with the goal that the x axis align - some charts have hourly data for a specific range, some have daily data, some have 5-minute data. One grid might have 2 y-axis, zero, or even 3. How to I Align them horizontally?
Image showing unaligned stacked highcharts
You can find a chart with the biggest plotLeft property and apply the same to the others by marginLeft property:
charts.forEach(function(ch) {
if (ch.plotLeft > maxPlotLeft) {
maxPlotLeft = ch.plotLeft;
}
});
charts.forEach(function(ch) {
ch.update({
chart: {
marginLeft: maxPlotLeft
}
});
});
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/5012/
API Reference:
https://api.highcharts.com/highcharts/chart.marginLeft
https://api.highcharts.com/class-reference/Highcharts.Chart#update
When using stacked columns, I would like the tooltip to be positioned above the stacked columns. Right now, the tooltip will appear above the hovered part of the column, like this:
I would like the tooltip to always appear above the stacked columns regardless of the hovered part, like this:
(source: i.ibb.co)
I know about the positioner method, but this function doesn't seem to receive the proper parameters for me to position the tooltip above the stacked columns. In particular I don't know how to properly get the coordinates of the hovered column, all I get is the global position of the cursor.
You can use the shared parameter for a tooltip:
tooltip: {
shared: true
}
Live demo: http://jsfiddle.net/BlackLabel/us4h659d/
API Reference: https://api.highcharts.com/highcharts/tooltip.shared
So I finally managed to do it using Axis.toValue() and Axis.toPixels() values:
https://api.highcharts.com/class-reference/Highcharts.Axis
For my solution to work you need to have a way to get the total value of a stacked column. There may be a way to do it using only the Highcharts object, but I don't like messing too much with the internals of Highcharts for compatibility reasons.
Here's what the positioner method could look like:
function positioner(labelWidth, labelHeight, point)
{
// Default position, assuming mChart is the Highcharts object
var chartY = point.plotY + mChart.plotTop;
var chartX = point.plotX + mChart.plotLeft;
// Move chartY above the stacked column, assuming getTotalColumnValue() exists
var category = Math.round(mChart.xAxis[0].toValue(point.plotX, true));
if(category in mChart.xAxis[0]['categories'])
chartY = mChart.yAxis[0].toPixels(getTotalColumnValue(category), false);
// Move tooltip above the point, centered horizontally
return {
x: chartX - labelWidth / 2,
y: chartY - labelHeight - 10,
};
}
I've developed a bunch of bar charts in HighCharts cloud with positive and negative values.
First question:
is it possible to have the xAxis appear at the 0 line (not at the bottom of the chart)?
What I've done so far is offset the xAxis so it's placed on the 0 line, which kinda works but I was hoping for a better solution. The other method I was think was to use plotLines code on the yAxis, but I don't get the ticks:
plotLines: [{
color: '#010101',
width: 2,
value: 0,
zIndex: 5
}],
Second question:
is it possible to have the tick marks to appear between each bar, and not just the bars that have an xAxis label?
This is what's rendering for me at the moment, and I'm trying to get a tick between all the bars while showing the same number of labels https://cloud.highcharts.com/show/cLtfEDClS
First question:
You can merge this configuration into chart options in Cloud’s custom code section:
chart: {
events: {
load: function() {
var yAxis = this.yAxis[0];
this.xAxis[0].update({
offset: -yAxis.toPixels(Math.abs(yAxis.min), true)
});
}
}
},
Demo: http://jsfiddle.net/BlackLabel/6712zrod/
It automatically positions x axis so that it works as y = 0 line.
Second question:
Try setting X Axis[0] > Labels > Step to 1.
API reference: https://api.highcharts.com/highcharts/xAxis.labels.step
Explanation from Docs:
To show only every n'th label on the axis, set the step to n. Setting the step to 2 shows every other label.
By default, the step is calculated automatically to avoid overlap. To prevent this, set it to 1. This usually only happens on a category axis, and is often a sign that you have chosen the wrong axis type.
I am working with XRange charts in High Charts where I have custom data labels for my data points. I face a similar problem in 2 scenarios:
When data label text is longer than width of corresponding data point range, it overflows outside and onto adjacent data points and hides their label, like this:
When scrolling across the x-axis, the data labels slide across and overflow even when the data point range isn't wide enough to show. This looks quite confusing;
.
You would notice it looks even worse here;
.
How do I fix this so that the data labels never flow outside the extent of the data point?
I have tried tweaking the "inside" parameter but it only ensures that the label doesn't flow into an adjacent row. Similarly, I looked at the crop and overflow options in the API but couldn't get it to work for me as needed.
I understand the width option in style might let me address the first problem, but I can't have a common absolute value in pixels for all labels as the width of each is dynamic. Also, the second problem still wouldn't be solved.
You can find both issues re-created here : https://jsfiddle.net/td0bsxg1/4/ . I need to handle both of them as gracefully as possible.
Do I need to change some parameter for the data labels?
dataLabels: {
enabled: true,
defer: false,
inside: true,
formatter: function () {
return 'Too Long Data Label';
}
}
You can dynamically set individual width style for each data label and define rules for them:
events: {
render: function() {
if (redrawEnabled) {
var points = this.series[0].points,
chart = this,
dataLabelWidth,
width;
redrawEnabled = false;
Highcharts.each(points, function(point) {
width = point.shapeArgs.width;
if (width < 20) {
point.dataLabel.hide();
} else {
point.dataLabel.show();
}
point.dataLabel.css({
width: width
});
});
chart.series[0].isDirty = true;
chart.redraw();
redrawEnabled = true;
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/wo0q9nzr/
I have a highstock chart witch candlestick data type.
When I mouseover the data point, I want to highlight the background of the point.
This is what tooltip -> crosshairs do:
tooltip: {
crosshairs: true
}
But the only width option to set is the fixed width. See http://jsfiddle.net/8YBd7/.
This fixed width works with initial zoom, but when I change the zoom, the width is not updated with new point width.
When I set 100% width, the crosshair would fill entire chart area:
tooltip: {
crosshairs: {
width: '100%'
}
}
Is there another option how to highlight current data point by changing its background or setting the width to the pointPixelInterval or something else?
Meanwhile, I produced a dirty workaround, so improvements are welcomed:
xAxis: {
events: {
afterSetExtremes: function() {
this.chart.tooltip.crosshairs = [];
this.chart.options.tooltip.crosshairs.width = (this.width / (this.series[0].points.length-1));
}
}
}
http://jsfiddle.net/QbdEu/1/
Whenever the zoom is changed, the width is recounted according to chart width and number of displayed data points. The width is not updated when calling redraw(), so the old crosshair needs to be removed.
Have you tried to use Renderer http://api.highcharts.com/highstock#Renderer.rect() which allows to plot any shapes and defined width? Only what you need is getting point width in pixels frpm(chart.series[0].data[0].graphic) and then setting correct widht of "shape".