I have requirement to extend date label formatting to show time period beside date when value is measured.
You can see on image how it should look.
Any way to achieve this by using format function of Highchart API?
EDIT: I need implementation without using third party solutions, since I need to embed solution into jasper report.
Thanks
As an alternative to use 'grouped categories' plugin, you can create additional xAxis labels by Highcharts. SVGRenderer.
chart: {
events: {
load: function() {
var chart = this,
ticks = chart.xAxis[0].ticks,
xy;
Highcharts.objectEach(ticks, function(tick) {
if ((tick.pos + 2) % 3 === 0) {
xy = tick.label.xy;
chart.renderer.text('date', xy.x, xy.y + 20)
.attr({
'align': 'center'
})
.add();
}
});
}
}
},
Live example: http://jsfiddle.net/BlackLabel/f7c54zop/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
Related
Currently I'm using css to remove my y-axis grid lines and labels like in the below image.
CSS:
.highcharts-yaxis-grid path:nth-child(1),.highcharts-yaxis-grid path:nth-child(2),
.highcharts-yaxis-grid path:nth-child(4),.highcharts-yaxis-grid path:nth-child(5){ stroke:transparent !important; }
.highcharts-yaxis-labels text:nth-child(1),.highcharts-yaxis-labels text:nth-child(2),
.highcharts-yaxis-labels text:nth-child(4),.highcharts-yaxis-labels text:nth-child(5){ fill:transparent !important; }
Whenever I download the chart as an image they reappear which makes sense as it doesn't see the css file I'm using.
I've tried to search for an answer on highcharts or anything on the net and haven't had luck, so here I am presenting this question.
For example in the load event you can remove specific labels and gridLines:
chart: {
events: {
load: function() {
var chart = this,
yAxis = chart.yAxis[0],
gridLines = yAxis.gridGroup.element.children,
ticks = yAxis.ticks,
tickPositions = yAxis.tickPositions;
gridLines[2].remove();
ticks[tickPositions[2]].label.element.remove();
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/5m0s7th2/
API Reference: https://api.highcharts.com/highcharts/chart.events.load
Using the accepted answer I did this in a loop to avoid losing my middle gridline and tick val.
events: {
load: function() {
var chart = this,
yAxis = chart.yAxis[0],
gridLines = yAxis.gridGroup.element.children,
ticks = yAxis.ticks,
tickPositions = yAxis.tickPositions;
var i = 4;
while(i > -1){
if(i !== 2){
gridLines[i].remove(); // the whole array element is removed from gridLines, so we're doing this backwards
ticks[tickPositions[i]].label.element.remove();
}
i--;
}
}
}
It became a problem when I was starting from 0 using either the accepted answer or my loop. Hope this helps anyone who may have a ton of gridlines.
I'm trying to add % after the 100 or -100 yAxis in the chart above.
I tried to add the % symbols like so:
quotes.data.frequency_counts[i].negative = Math.round(negative * -1)+'%';
quotes.data.frequency_counts[i].positive = Math.round(positive)+'%';
However got an error saying strings are not allowed as data_points, which makes sense, but still hoping there is a way to get the % sign displayed so the user knows what we are showing them.
This isn't my app, however it is a HighChart that is editable in plunker: http://plnkr.co/edit/8mDQD1?p=preview
You can use a label formatter for that:
yAxis: {
title: { text: 'Temperature (Celsius)' } ,
labels: {
formatter: function() {
return this.value + '%';
}
}
}
Here's an updated (now nonsensical) Plunker showing the changes
Is there a way to update the x-axis on a real time flot chart?
I want something like this -> (http://www.flotcharts.org/flot/examples/realtime/index.html)
but as you can see, there are no values on the x-axis..
So, is there a way to shift the x-axis values as the chart shifts?
Thanks in advance!
You first need to show the x axis:
var plot = $.plot("#placeholder", [ getRandomData() ], {
xaxis: {
show: true
}
});
Then on every data update you need to update the grid as well:
function update() {
plot.setData([getRandomData()]);
plot.setupGrid(); // updating the grid
plot.draw();
setTimeout(update, updateInterval);
}
Check this plunker for example.
I've been using the following code to set dataLabels for bar charts in Highcharts...
plotOptions: {
bar: {
dataLabels: {
enabled: true,
formatter: function() {
if (this.y==null) {
return '<i>(Suppressed)</i>';
} else {
return '';
}
}
}
}
}
Basically, I want to be able to show the user when a value has been hidden for privacy reasons.
In previous versions of Highcharts, the label would show up for the null values as I desired. In version 3.0.8, I do not get any dataLabels for the null vales.
Is there a workaround or fix for this?
Possibly bug, reported here https://github.com/highslide-software/highcharts.com/issues/2899
Workaround: use renderer http://api.highcharts.com/highcharts#Renderer.text
As Sebastian points out, this is in fact a bug. However, there is an easy fix... In highcharts.src.js, simply change the call to the pick function for getting plotX and plotY in Series.prototype.alignDataLabel (lines 16132 and 16133) to:
plotX = pick(point.plotX, 0),
plotY = pick(point.plotY, 0),
rather than
plotX = pick(point.plotX, -999),
plotY = pick(point.plotY, -999),
Hope this ends up being helpful to somebody...
I was having a hard time trying to figure out how to center labels on a datetime x-axis in Highcharts without using categories and tickPlacement (since tickPlacement only works on categories).
My axis was dynamically created so I could not simply set an x-offset or padding, as this would cause axes of different intervals to look strange.
After messing around with the config options I think I may have found a solution using the x-axis formatter and some css / jquery noodling in the Highcharts callback. See my answer below.
The trick is to use the x-axis labels object like this:
xAxis: {
type: 'datetime',
labels: {
useHTML: true,
align: 'center',
formatter: function () {
//using a specific class for the labels helps to ensure no other labels are moved
return '<span class="timeline_label">' + Highcharts.dateFormat(this.dateTimeLabelFormat, this.value) + '</span>';
}
}
You can see that the formatter will keep whatever dateTimeLabelFormat has been set by the user or default.
Then have a callback that does something like this:
function (chart) {
var $container = $(chart.container);
var $labels = $container.find('.highcharts-axis-labels .timeline_label');
var $thisLabel, $nextLabel, thisXPos, nextXPos, delta, newXPos;
$labels.each(function () {
$thisLabel = $(this).parent('span');
thisXPos = parseInt($thisLabel.css('left'));
$nextLabel = $thisLabel.next();
nextXPos = $nextLabel.length ? parseInt($nextLabel.css('left')) : chart.axes[0].left + chart.axes[0].width;
delta = (nextXPos - thisXPos) / 2.0;
newXPos = thisXPos + delta;
if ($nextLabel.length || $(this).width() + newXPos < nextXPos) {
$thisLabel.css('left', newXPos + 'px');
} else {
$thisLabel.remove();
}
});
});
In short, this will go through each label and determine how much it should be moved over (using css) by calculating the distance between itself and the next label. When it reaches the the last label, it either moves it over using the end of the axis for the calculation or removes it if it won't fit. This last part is just the decision I decided to make, you can probably choose to do something else like word wrap, etc.
You can see the jsfiddle here
Hope this helps some people. Also, if there are any improvements it would be great to see them here.
Based on the existing answer, there is a much simpler solution that also works when resizing the browser window (or otherwise forcing the chart to redraw), even when the tick count changes: http://jsfiddle.net/McNetic/eyyom2qg/3/
It works by attaching the same event handler to both the load and the redraw events:
$('#container').highcharts({
chart: {
events: {
load: fixLabels,
redraw: fixLabels
}
},
[...]
The handler itself looks like this:
var fixLabels = function() {
var labels = $('div.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'))) / 2
);
$(labels.get(this.xAxis[0].tickPositions.length - 1)).remove();
};
As you see, the extra wrapping of labels is unnecessary (at least if you do not have more than one xAxis). Basically, it works like this:
Get all existing labels (when redrawn, this includes newly added ones). 2. Sort by css property 'left' (they are not sorted this way after some redrawing)
Calculate offset between the first two labels (the offset is the same for all labels)
Set half of the offset as margin-left of all labels, effectively shifting them half the offset to the right.
Remove the rightmost label (moved outside of chart, by sometimes partly visible).