This is a question for anyone with HighchartsJS experience
I’m currently having an issue displaying state data using the Highcharts X-range series charts. Specifically, My problem is that our data that we are using to represent each individual state are both fairly high and non consecutive (768, 769 and 773). To label these individual states I’m using a sparse array and placing my labels at the corresponding indices.
The problem I am trying to solve which is depicted by this jsfiddle: https://jsfiddle.net/sn4d2hvq/10/
let categoryArray = [];
categoryArray[768] = 'one';
categoryArray[769] = 'two';
categoryArray[773] = 'three';
Highcharts.chart('container', {
chart: {
type: 'xrange'
},
title: {
text: 'Example'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: ''
},
categories: categoryArray,
},
series: [{
name: 'dataset 1',
borderColor: 'gray',
pointWidth: 20,
data: [{
x: Date.UTC(2014, 10, 21),
x2: Date.UTC(2014, 11, 2),
y: 768,
}, {
x: Date.UTC(2014, 11, 2),
x2: Date.UTC(2014, 11, 5),
y: 769
}, {
x: Date.UTC(2014, 11, 8),
x2: Date.UTC(2014, 11, 9),
y: 773
}, {
x: Date.UTC(2014, 11, 9),
x2: Date.UTC(2014, 11, 19),
y: 769
}, {
x: Date.UTC(2014, 11, 10),
x2: Date.UTC(2014, 11, 23),
y: 773
}],
dataLabels: {
enabled: true
}
}]
});
is that I want to exclude all values (which in this case means all numerical values) on the y-axis such that there are no numbers from zero up until the first index as well as no numbers in between any of the labels (ie. 770, 771,772). Here’s an example of the desired view:
https://jsfiddle.net/estgbr6j/2/
let categoryArray = ['one', 'two', 'three'];
Highcharts.chart('container', {
chart: {
type: 'xrange'
},
title: {
text: 'Example'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: ''
},
categories: categoryArray,
},
plotOptions: {
xrange: {
colorByPoint: false,
}
},
series: [{
name: 'dataset 1',
borderColor: 'gray',
pointWidth: 20,
data: [{
x: Date.UTC(2014, 10, 21),
x2: Date.UTC(2014, 11, 2),
y: 0,
}, {
x: Date.UTC(2014, 11, 2),
x2: Date.UTC(2014, 11, 5),
y: 1
}, {
x: Date.UTC(2014, 11, 8),
x2: Date.UTC(2014, 11, 9),
y: 2
}, {
x: Date.UTC(2014, 11, 9),
x2: Date.UTC(2014, 11, 19),
y: 1
}, {
x: Date.UTC(2014, 11, 10),
x2: Date.UTC(2014, 11, 23),
y: 2
}],
dataLabels: {
enabled: true
}
}]
});
The only way I’ve been able to consistently achieve the desired result (as depicted by the second example) has been to map the values from [768, 769, 773] => [0, 1, 2] and use a dense array to label the newly mapped values. It seems that this workaround shouldn’t be necessary but I have yet to find an option in the highcharts API to easily allow for our desired result without mapping the values. It should also be noted that in our actual data set, we are usually displaying multiple series with each series depicted by its own color rather than each category (which I have been able to achieve). I would like to know which API option or options are available to display our desired result. Thank you so much.
highcharts: 9.0.1
highcharts-angular: 2.10.0
angular: 12.0.5
node: 14.18.0
The solution with mapping your data is really good. The intervals must be regular if you want to have equally distributed points.
data: [{
x: Date.UTC(2014, 10, 21),
x2: Date.UTC(2014, 11, 2),
y: 0,
}, {
x: Date.UTC(2014, 11, 2),
x2: Date.UTC(2014, 11, 5),
y: 1
}, {
x: Date.UTC(2014, 11, 8),
x2: Date.UTC(2014, 11, 9),
y: 2
}, {
x: Date.UTC(2014, 11, 9),
x2: Date.UTC(2014, 11, 19),
y: 1
}, {
x: Date.UTC(2014, 11, 10),
x2: Date.UTC(2014, 11, 23),
y: 2
}]
You can use tickPositions property, but labels will not be equally distributed. Example: https://jsfiddle.net/BlackLabel/gbwhk5nx/
API Reference: https://api.highcharts.com/highcharts/yAxis.tickPositions
mateusz.b on the official Highcharts forum had a great answer to this. He suggested using a columnrange series instead of an xrange series to present the data.
Check out the post here:
https://www.highcharts.com/forum/viewtopic.php?f=9&t=47822
Related
I have a Gantt chart and I wanna plot a band only on a specific row. On my example below it displays on every row.
It can be a band plot or something similar (eg: SVG, bar, ...). As long as can control easily the position with start and end in time since I'll have a few for over 30 rows in different positions.
Here's a fiddle
And my code:
// THE CHART
Highcharts.ganttChart('container', {
title: {
text: 'Gantt Chart with Progress Indicators'
},
yAxis: {
categories: ['1', '2']
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
verticalAlign: "top",
format: "{point.custom.label}"
}
}
},
xAxis: {
plotBands: [{
color: '#B3D1AE', // Color value
from: Date.UTC(2014, 10, 21), // Start of the plot band
to: Date.UTC(2014, 10, 22) // End of the plot band
}],
},
series: [{
type: 'line',
zoneAxis: 'x',
zones: [{
value: Date.UTC(2014, 10, 20)
}, {
dashStyle: 'dot',
value: Date.UTC(2014, 10, 25)
}],
data: [{
y: 0,
x: Date.UTC(2014, 10, 18),
custom: {
label: 1
}
}, {
y: 0,
x: Date.UTC(2014, 10, 25, 12),
custom: {
label: 2
}
}]
}, {
name: 'Project 1',
type: 'line',
zoneAxis: 'x',
zones: [{
value: Date.UTC(2014, 10, 28)
}, {
dashStyle: 'dot',
value: Date.UTC(2014, 10, 29)
}],
data: [{
x: Date.UTC(2014, 10, 25, 16),
y: 0,
custom: {
label: 3
}
}, {
x: Date.UTC(2014, 10, 29),
y: 0,
custom: {
label: 4
}
}]
}, {
type: 'line',
zoneAxis: 'x',
data: [{
x: Date.UTC(2014, 10, 25, 16),
y: 1,
custom: {
label: 3
}
}, {
x: Date.UTC(2014, 10, 29),
y: 1,
custom: {
label: 4
}
}]
}]
});
You can use SVG.Renderer to draw the "plotBands" and axis.toPixels() method to control the position.
Example:
chart: {
events: {
load() {
let from = this.xAxis[0].toPixels(Date.UTC(2014, 10, 21)),
to = this.xAxis[0].toPixels(Date.UTC(2014, 10, 22)),
width = to - from,
rowStart = this.yAxis[0].toPixels(0.5),
rowHeight = this.yAxis[0].toPixels(1) - this.yAxis[0].toPixels(0);
this.renderer.rect(from, rowStart, width, rowHeight)
.attr({
fill: '#ff0000',
zIndex: 0
}).add()
}
}
}
Demo:
https://jsfiddle.net/BlackLabel/qbo8Lmy6/
API References:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer
https://api.highcharts.com/class-reference/Highcharts.Axis#toPixels
I have an x-range highchart which is used to display an event timeline. I was able to make it work for events which has start and end date. But I have events that are not yet ended and for those I need to extend the data point of the chart without stopping like below. Green event hasn't finished yet.
Following is my existing code:
Highcharts.chart('container', {
chart: {
type: 'xrange',
height: 100
},
title: {
text: ''
},
xAxis: {
visible: true,
tickLength: 0,
lineWidth: 6,
lineColor: '#000',
labels: {
enabled: false
}
},
yAxis: {
visible: false
},
legend: {
enabled: false
},
series: [{
name: '',
borderRadius: 0,
pointPadding: 0,
borderWidth: 6,
groupPadding: 0,
data: [{
x: Date.UTC(2014, 10, 21),
x2: Date.UTC(2014, 11, 2),
y: 0,
color: 'transparent',
borderColor: 'rgba(230, 141, 11, 0.5)'
}, {
x: Date.UTC(2014, 10, 26),
x2: Date.UTC(2014, 11, 5),
y: 0,
color: 'transparent',
borderColor: 'rgba(228, 53, 70, 0.5)'
}, {
x: Date.UTC(2014, 11, 8),
x2: Date.UTC(2014, 11, 10),
y: 0,
color: 'transparent',
borderColor: 'rgba(40, 167, 69, 0.5)'
}, {
x: Date.UTC(2014, 11, 9),
x2: Date.UTC(2014, 11, 12),
y: 0,
color: 'transparent',
borderColor: 'rgba(40, 147, 164, 0.5)'
}],
dataLabels: {
enabled: false
}
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/xrange.js"></script>
<div id="container"></div>
I tried putting Date.UTC(0, 0, 0) for the x2 but it didn't work as expected. Is this possible with xrange charts in highcharts. Thanks in advance!
You can set the x2 value to a later date than xAxis.max:
xAxis: {
...,
max: Date.UTC(2014, 11, 5)
},
...,
series: [{
data: [{
x: Date.UTC(2014, 10, 26),
x2: Date.UTC(2014, 11, 15),
...
}],
...
}]
Live demo: http://jsfiddle.net/BlackLabel/9f6Lejbs/
API Reference: https://api.highcharts.com/highcharts/xAxis.max
How can I set the height of each bar in xrange charts? I don't want to specify the height of the whole chart, instead the height of each single bar.
This type of chart (as in the link):
http://jsfiddle.net/vqpjL3ns/1/
height of bar
You should create separate series for each data point, than you will be able to set different width for each bar:
series: [{
name: 'Project 1',
pointWidth: 20,
data: [{
x: Date.UTC(2014, 10, 21),
x2: Date.UTC(2014, 11, 2),
y: 0,
partialFill: 0.25
}],
dataLabels: {
enabled: true
}
}, {
pointWidth: 15,
data: [{
x: Date.UTC(2014, 11, 2),
x2: Date.UTC(2014, 11, 5),
y: 1
}]
}, {
pointWidth: 30,
data: [{
x: Date.UTC(2014, 11, 8),
x2: Date.UTC(2014, 11, 9),
y: 2
}]
}, {
pointWidth: 40,
data: [{
x: Date.UTC(2014, 11, 9),
x2: Date.UTC(2014, 11, 19),
y: 1
}]
}, {
pointWidth: 10,
data: [{
x: Date.UTC(2014, 11, 10),
x2: Date.UTC(2014, 11, 23),
y: 2
}]
}]
Live demo: http://jsfiddle.net/BlackLabel/4uydm6tr/
API: https://api.highcharts.com/highcharts/series.xrange.pointWidth
I know that the title sounds confusing, but it wasn't easy finding a sentence for this problem, so I'll try to explain further.
I am trying to display a history of how many test cases there have been created for each day for given platforms. The y value reprents amount of current test cases while the "expected" is the the amount of test cases each serie require in order to reach the goal.
Can I somehow make y-axis display the expected value? So let's if I want to look at the IOS serie only, then it should know that the moment y and expected are identical it should fill 100% and not 12% of the plot. The same goes for when 2 test cases have been created while the expected value is 6, then it should fill 33% and not 2%.
http://jsfiddle.net/dWDE6/1201/
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
tooltip: {
shared: true,
pointFormat: '{series.name}: <b>{point.y} / {point.expected}</b><br/>',
},
xAxis: {
type: 'datetime'
},
yAxis: {
allowDecimals: false,
title: {
text: 'Test cases'
},
labels: {
formatter: function() {
return this.value + "%";
}
},
min: 0,
max: 100
},
series: [{
name: 'IOS',
data: [{
x: Date.UTC(2017, 09, 15),
y: 2,
expected: 6
}, {
x: Date.UTC(2017, 09, 16),
y: 3,
expected: 6
}, {
x: Date.UTC(2017, 09, 17),
y: 6,
expected: 6
}]
}, {
name: 'Android',
data: [{
x: Date.UTC(2017, 09, 15),
y: 2,
expected: 12
}, {
x: Date.UTC(2017, 09, 16),
y: 3,
expected: 12
}, {
x: Date.UTC(2017, 09, 17),
y: 12,
expected: 12
}]
}, {
name: 'Windows',
data: [{
x: Date.UTC(2017, 09, 15),
y: 6,
expected: 12
}, {
x: Date.UTC(2017, 09, 16),
y: 8,
expected: 12
}, {
x: Date.UTC(2017, 09, 17),
y: 14,
expected: 12
}]
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px"></div>
Here is one way to achieve what you are after.
http://jsfiddle.net/ewolden/dWDE6/1202/
I changed your point style to the following:
actual: 2,
expected: 6,
y: 2/6*100
And the following pointFormat:
pointFormat: '{series.name}: <b>{point.actual} / {point.expected}</b><br/>'
I am using Highcharts with the xrange plugin, as seen in this fiddle here.
As seen in the dataobject, I have two areas that overlap:
data: [{
x: Date.UTC(2015, 0, 1),
x2: Date.UTC(2020, 11, 2),
y: 0
}
,{
x: Date.UTC(2015, 0, 1),
x2: Date.UTC(2020, 5, 2),
y: 0
}
, {
x: Date.UTC(2015, 0, 2),
x2: Date.UTC(2020, 11, 5),
y: 1
}]
Is there a Highcharts way to group a 'y row' according to the rowLabel, as is done in google charts, as seen below?
var options = {
**timeline: { groupByRowLabel: true},**
backgroundColor: 'white',
avoidOverlappingGridLines: true,
tooltip: { isHtml: false }
};
I would like to create this without creating a new row (e.g. y:3), as this causes spacing, alternating colours and visual confusion in the dataset.
EDIT: Here is what I am looking for: