I have 2 Series on one graph. Only one series can show at a time but the hidden graph affects the range on the x-axis.
The data is dynamically generated via PHP but here is 2 fiddles to show what I mean:
Fiddle With Changed Scale and Hidden Data
Fiddle With removed Hidden Data and correct scale
This code snippet is to ensure that only one series can be shown at any given time.
events: {
show: function () {
var chart = this.chart,
series = chart.series,
i = series.length,
otherSeries;
var seriesName = this['options']['name'];
chart.yAxis[0].axisTitle.attr({
text: seriesName
});
while (i--) {
otherSeries = series[i];
if (otherSeries != this && otherSeries.visible) {
otherSeries.hide();
}
}
}
I am not sure why the graph with the hidden data shows until 16:00 but the graph without any additional data shows until the last data point at 15:38
It appears that Highcharts is taking into account the pointRange of the series with the largest pointRange (although it is hidden) and displaying the x-axis based on that. The range of your "Calls/Hour" series is 1 hour, so it makes sure that if that series had a point at the very end, it would still have room to show.
I'm not sure if there's any elegant way of solving this, but a bit of a "hack" in your case is to change the pointRange of all series to that of the currently showing one.
My crude implementation of this has three changes to your code:
Your series that are visible: false by default also get pointRange: 1 so they don't disrupt the x-axis range for the only visible series.
When the chart has been created we store the correct point range of each series for future reference, for example with the callback function:
$('#callFrequencyGraph').highcharts({
// Options...
}, function(event) {
var series = this.series;
// Store the correct point ranges
for(var i = 0; i < series.length; i++) {
series[i].update({
historicalPointRange: (series[i].closestPointRange ? series[i].closestPointRange : 3600000)
}, false);
this.redraw();
}
}
Extend your events.legendItemClick function to update all series pointRange to that of the series which will be showing after the click is completed:
legendItemClick: function() {
if(this.visible){
return false;
}
else {
var series = this.chart.series;
for(var i = 0; i < series.length; i++) {
series[i].update({
pointRange: this.options.historicalPointRange
}, false);
}
}
}
See this updated JSFiddle for the result of all these changes.
Edit: jsFiddle Update for bug
Related
In the highcharts example above suppose I have 100 series in Bananas which is 1 right now and just one series in Apples ,and if there is a lot of empty space between Bananas and Oranges can we reduce the spacing between them ?
The reason is if there are 100 series in Bananas due to space constraint every line gets overlapped even though there is extra space available between Bananas and Apples . Also is it possible to remove "Oranges" if it doesnt have any series at all and accomodate only series from "Bananas"?
Categories functionality works only for constant tick interval equaled to 1. What you're trying to achieve is having a different space reserved for every category. That means that tick interval has to be irregular.
Unfortunately Highcharts doesn't provide a property to do that automatically - some coding and restructuring the data is required:
All the points have specified x position (integer value)
xAxis.grouping is disabled and xAxis.pointRangeis 1
Following code is used to define and position the labels:
events: {
render: function() {
var xAxis = this.xAxis[0];
for (var i = 0; i < xAxis.tickPositions.length; i++) {
var tickPosition = xAxis.tickPositions[i],
tick = xAxis.ticks[tickPosition],
nextTickPosition,
nextTick;
if (!tick.isLast) {
nextTickPosition = xAxis.tickPositions[i + 1];
nextTick = xAxis.ticks[nextTickPosition];
tick.label.attr({
y: (new Number(tick.mark.d.split(' ')[2]) + new Number(nextTick.mark.d.split(' ')[2])) / 2 + 3
});
}
}
}
}
(...)
xAxis: {
tickPositions: [-0.5, 6.5, 7.5],
showLastLabel: false,
labels: {
formatter: function() {
switch (this.pos) {
case -0.5:
return 'Bananas';
case 6.5:
return 'Apples';
}
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/2Lcs5up5/
The data series in my HighCharts chart only includes dates from the past few days, but the chart's x-axis and zoom bar show a date range all the way back to 1970.
How can I limit the presented date range so it only goes back as far as the first date present in the series data?
Example
HTML
<div id="chart_container" style="height: 500px></div>
JavaScript
$(function () {
var timestamps = [1481000484000,1481108510000,1481215541000,1481316568000,1481417583000];
var series_raw_data = [100,300,750,400,200];
// prepare data
var points = [[],[]];
for (var i = 0; i < timestamps.length; i++) {
points.push([timestamps[i], series_raw_data[i]]);
}
// create chart
$('#chart_container').highcharts('StockChart', {
series: [{
data: points
}]
});
});
Here's Fiddle1 which shows the behavior.
I also tried setting the xAxis 'min' option to the first timestamp, and setting the axis type to 'datetime', but those didn't help - Fiddle2.
The reason why it happens is your points array.
If fact, after filling, it looks like this:
points = [ [], [], [x, y], [x, y]]
Those two empty arrays create unwanted behaviour.
Fix the initial array and it works
var points = [];
example: https://jsfiddle.net/hbwosk3o/3/
I am working with the Highstock compare demo:
http://www.highcharts.com/stock/demo/compare
jsFiddle:
http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/stock/demo/compare/
The associated code of the percent compare is as follows:
plotOptions: {
series: {
compare: 'percent'
}
},
If we set the rangeSelector to 1m (one month), and assuming today is August 15, 2016, then the first entry displayed is Tuesday, July 12. The values are MSFT: 53.21, AAPL: 97.42, and GOOG: 720.64. The Tooltip shows percentage changes of +1.18%, +0.45%, and +0.78%, respectively, over the previous day. But the problem is that the values for the previous day (7/11/2016) are not shown. This is confusing to the user, in my opinion. What I want to do instead is give each of these starting values a percentage change of 0%, so the left-side of the graph always starts at the origin. How do I do this?
UPDATE: I was thinking along the lines of something like this:
events: {
load: function(e) {
set_new_min_y_data_points(e);
}
}
// ...
function set_new_min_y_data_points(e) {
for (var i = 0; i < e.target.series.length; ++i) {
// By setting the first data point to the same
// value as the second data point, we ensure
// that the series starts at the origin.
e.target.series[i].processedYData[0] = e.target.series[i].processedYData[1];
}
}
...but this doesn't work. Even though the values of e.target.series[i].processedYData[0] are changed, the graph looks the same.
On a Highcharts chart with datetime axis, I am trying to highlight weeks. First, I had the idea to use the grid and to set tickInterval to 7*24*60*60*1000 and minorTickInterval to 24*60*60*1000. With the option gridLineWidth set to 2, the result is almost perfect.
The problem is when zooming: minor ticks appears but without label. I can not find how to add it. And the labels are not dynamic.
You can try this demo: https://jsfiddle.net/gdebrion/19x4nmp5/19/
First chart is the basic one. When you zoom you can see the changes in x-axis.
Second chart is mine. The weeks are visible but when zooming in until having a day display on the full width, and the only ticks visible are the minor one, without label…
Please tell me if you have an idea. Thanks!
The API does not provide a way to display labels on minor ticks.
http://www.highcharts.com/docs/chart-concepts/axes
MINOR TICKS
If the minorTickInterval option is set, minor ticks are laid out between the major ones. This includes minor tick marks, and minor grid lines, which have their own options for look and feel, but excludes labels.
Having a peek at the source code for Highcharts, I also do not see any label representation for minor ticks as there are for the major ticks (axis.labelEdge = [];) .
https://github.com/highcharts/highcharts/blob/b6bc666da00d37c5c4e3c0d7fe238b8526e583ea/js/parts/Axis.js
...
// Major ticks
axis.ticks = {};
axis.labelEdge = [];
// Minor ticks
axis.minorTicks = {};
// List of plotLines/Bands
...
UPDATE:
Here is a slightly rough solution to enable minor tick labels for highcharts:
http://jsfiddle.net/strince/deuez7gk/
The code doesn't handle overlapping labels when the zoom is far out so you'll need to zoom in a bit to see it work.
The chart code was updated with:
// Keep track of elements created.
var minorTickLabels = new Array();
...
events: {
load: function() { addMinorTickLabels(this); },
redraw: function() { addMinorTickLabels(this); }
}
...
function addMinorTickLabels(chart) {
// The elements need to be destroyed, otherwise a dictionary
// internal to highcharts will accumulate and pollute the chart.
for (var i = 0; i < minorTickLabels.length; i++) {
var textItem = minorTickLabels[i];
textItem.destroy();
}
minorTickLabels = new Array();
var axis0 = chart.xAxis[0];
var lastIndexFound = 0;
for (var tick in axis0.minorTicks) {
var el = axis0.minorTicks[tick];
// Skip double labels on major ticks.
var index = axis0.tickPositions.indexOf(el.pos, lastIndexFound);
if (index >= 0) {
listIndexFound = index;
continue;
}
var xPos = el.mark.getBBox().x;
var yPos = el.mark.getBBox().y;
var labelText = 0;
// The formatting parameters below should be passed in.
var textItem = chart.renderer.text(Highcharts.dateFormat("%d. %b", el.pos), xPos, yPos)
.css({
color: '#101010',
fontSize: '8px'
})
.attr({
rotation: -25,
zIndex: 6
});
// Add the tick label to the chart.
textItem.add();
minorTickLabels.push(textItem);
}
};
I have a spiderweb graph with just the one data series. In the interests of printing I'd like to incorporate the value plotted in the label after the actual label name but I can't seem to work out how to do so.
This example to help explain what I mean is a bar-graph that I found in my search. The code layout is similar and a lot less cluttered than mine and I'm fairly sure a solution on this one would be easily transferable.
labels: {
formatter: function() {
return this.value + ' XX.X';
}
}
JSFiddle Here
So for the X axis I'm trying to replace the "XX.X" with the relevant Y value to get the labels: "Foo 29.9 | Bar 71.5 | Foobar 106.4"
I dug through "this" in the xAxis labels formatter and got as far as finding the Y figures at "this.chart.series[0].yData", but couldn't work out a way to associate these back to each relevant X label, and I thought it seemed the wrong way of going about things anyway.
You can do this after rendering of the chart in the chart.events.load method using setCategories. This code below assumes that each index element on the xAxis has a corresponding data element. If it doesn't then you would need to handle that case.
chart: {
events: {
load: function (event) {
var cats = this.xAxis[0].categories;
var theData = this.series[0].data;
var newCats = [];
for (var i = 0; i < cats.length; i++) {
newCats.push(cats[i] + ' ' + theData[i].y)
}
this.xAxis[0].setCategories(newCats);
}
}
}
Live demo.