I looking for a way to only draw part of the data set in area chart. There is a slider above the chart that can limit the range of one series in the chart while other stile rendered in whole. I wonder whats the best way to do this. The only idea at the moment is to redraw the chart every time the slider moves but I'm afraid this could result in worse performance. Maybe this could be done with something like mask on the SVG element.
I came up with a simple solution by just clipping the svg graph with an clip path:
//var chart is the actual HighChartsInstance;
var renderer = chart.renderer;
var group = renderer.g().add();
var clipPath = renderer.createElement("clipPath");
clipPath.element.id = 'clip';
var rect = renderer.rect(0, 0, 200, 400).add(clipPath);
this.clippingMask = rect.element; //reference to the clipping rect which width is changed by the slider
clipPath.add(group);
chart.series[1].group.element.setAttribute('clip-path', "url(#clip)");
chart.series[1].group.element.childNodes[0].setAttribute('clip-path', "url(#clip)");
You have a few ways
use highstock which contains "slider" http://www.highcharts.com/stock/demo/
use highstock.js and highcharts chart with scroller http://jsfiddle.net/UCmUx/
scrollbar:{
enabled:true
},
use highcharts chart without scroller http://jsfiddle.net/UCmUx/1/ and in case when you move your own scroller, then use setExtremes() http://api.highcharts.com/highcharts#Axis.setExtremes()
I think one option is to modify the series data which you want to restrict, and then call:
chart.series[n].setData(newData);
where 'n' is the number of the series you are truncating. newData is a copy of the series data with the unwanted points taken out. You will need to specify x and y values in the series in order for it to be plotted in the correct position.
Related
I am using Highcharts and have initialized a pie chart, but with 4 pies in it, lined up in a row. Each pie has 2 slices, the second one is always transparent and has no datalabel, so every single chart has only 1 data label to show a value.
The only thing I want is to center the data label below the pie chart.
The problem is that dependent on the size of the visible slice the data label is moving because it is kinda bound to it?
Image to show the problem and the current state:
I tried to position the labels by using x and distance:
plotOptions: {
pie: {
dataLabels: {
distance: 0,
x: -100
which is actually working; I would have to fix the position for each chart and its data label.
But since the chart data can be changed by click the filled slice will change and so the data labels would reposition themselves. So I kinda need a way to fix their position relative to the center of the chart or something like that.
Thanks to Sebastian Bochan for the comment. I ended up using the renderer:
this.renderer.label(
this.series[0].data[0].name + '<br>'
+ Highcharts.numberFormat(this.series[0].data[0].percentage, 2)+'%',
80, 320,'callout')}).add();
Just an example. The 80 and 320 here set the position of the label in the plot area. Renderer
I have some pie charts on my site and they show quite a bit of data. I was wondering if there is a way to load the data, but initially hide any data that is less than some arbitrary value. When I say hide, I mean in the same way you can hide the certain data by clicking on the label in the legend. Then through the legend, have the user be able to show this data on the graph by clicking on the label in the legend. Is there a property or something I can use to accomplish this?
You can define any variable as maxValue, then iterate on each point and call setVisible as false.
var minValue = 10
$.each(chart.series[0].data, function(i, point){
if(point.y < minValue) {
point.setVisible(false);
}
});
Example: http://jsfiddle.net/ct2jejgv/
Simply use this.chart.series[i].hide() / .show(). In your script, manually search for series less than your value and hide them like above. Its a simple foreach.
I am drawing a line chart with monthly data points. However, I want the scale to display year strings only.
So far, so easy. However, as far as I can see, Highcharts will always draw the xAxis labels relative to the ticks... and I am required to display them centered between ticks.
Is there some simple way of doing this that I am missing, please...?
According to my understanding, the behavior you desire is: http://jsfiddle.net/msjaiswal/U45Sr/2/
Let me break down the solution :
1. Monthly Data Points
One data point corresponding to one month :
var data = [
[Date.UTC(2003,1),0.872],
[Date.UTC(2003,2),0.8714],
[Date.UTC(2003,3),0.8638],
[Date.UTC(2003,4),0.8567],
[Date.UTC(2003,5),0.8536],
[Date.UTC(2003,6),0.8564],
..
]
2. Scale to display only yearly ticks
Use chart options like this:
xAxis: {
minRange : 30 * 24 * 3600 * 1000, //
minTickInterval: 12* 30 * 24 * 3600 * 1000 // An year
},
There is no simple, out-of-the-box solution. You have to use events and reposition the labels accordingly. Here is a sample 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();
};
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).
This can be done with a workaround by manually adjusting the label positioning via a callback (called on both load and redraw). Please see the fiddle linked to in my comment on this post: Highcharts - how can I center labels on a datetime x-axis?
There are several xAxis options which may help do what you want.
http://api.highcharts.com/highcharts#xAxis.labels
Take a look at 'align' which specifies whether the labels are to the left or right of the tick, and also 'x' which allows you to specify a x-offset for the label from the tick.
Have you tried to use tick placement ? http://api.highcharts.com/highcharts#xAxis.tickmarkPlacement
In a Highcharts column chart we'd like to highlight one value/sample by drawing its column a little bit wider... But this seems not to be possible, is it?
pointWidth only affects the whole series.
Maybe I could overlay a second series, but IMHO that's not a nice solution.
You can also use data attribute and modify width.
http://jsfiddle.net/cDvmy/2/
chart.series[0].data[0].graphic.attr({
width:50
});
I don't see any way to do this with the current API. As an equally not nice solution you could adjust the SVG after the plot is drawn:
// make fifth bar of first series wider
var bar = $($('.highcharts-series').children()[4]);
bar.attr('width',parseInt(bar.attr('width'))+20);
bar.attr('x',parseInt(bar.attr('x'))-10); // keep it centered
Fiddle here.
I have a HighStock chart that is pulling in some OHLC data and creating a chart with 3 series - 1 candlestick, 1 volume, and 1 set of flags. This all works fine.
I want to add some custom trend lines to the chart. I will determine the points and do the paths based on custom logic.
The problem is that when I use the Renderer from the Chart to draw my path, the path is not connected to the underlying chart. As the chart date range is modified and/or new points are added to the primary series, the placement and size of my custom path remains unchanged. It is constant.
I need the location/endpoints of the custom path to be tied to the datapoints of the chart, not the coordinates of the svg drawing. Is there a way to accomplish this?
Here is the portion of the code that is adding a simple path from pointa to pointb. The path renders as expected but is then static:
buildPath: function(pointa, pointb){
this.myChart.renderer.path(this.buildPathArray(pointa,pointb))
.attr({
'stroke-width': 2,
stroke: 'red'
}).add();
},
buildPathArray: function(pointa, pointb){
var pathArray = [];
pathArray.push('M');
pathArray.push(pointa.plotX);
pathArray.push(pointa.plotClose);
pathArray.push('L');
pathArray.push(pointb.plotX);
pathArray.push(pointb.plotClose);
pathArray.push('Z');
return pathArray;
}
Per request, I created a JS Fiddle that demonstrates the general issue.
Any help is much appreciated.
SOLVED
This doesn't seem to come for free with Highcharts. Or if it does I did not find out the technique.
I had to use both the load and redraw events of the chart object contained in my StockChart.
On load, I draw the initial paths, aligned with the Point objects involved in my trending lines. As I build these path objects (SVGElement objects containing the genuine SVG path elements) I keep track of them in an array.
On redraw, I have to both destroy the old trend lines and create new ones. So I loop over my array of old elements and remove each from their own parentNode. Then I draw a fresh version of my trend lines based on the newly plotted location of each of my relevant Point objects.
The end result is that on each redraw event, the lines appear to move with the chart, when they're really being destroyed and recreated.