I need help to create a Hichart gantt with out overlapping the bar. need to have the data grouped and not to overlap each other. EX:
Resource 1 Task A and Task B over lap each other, is there any possibility to place Task B below Task A or any other ideas?
Fiddle
series: [{
name: 'Resource 1',
data: [{
name: 'Task A',
y: 0,
start: today - (2 * day),
end: today + (6 * day)
}, {
name: 'Task B',
y: 0,
start: today - (3 * day),
end: today + (6 * day),
color: 'rgba(140, 140, 140, 0.7)'
}, {
name: 'Task C',
y: 0,
start: today + (13 * day),
end: today + (17 * day)
}]
}
Unfortunately, this feature is not supported yet. However, the workaround is to use yAxis.breaks to make the first category bigger. Then, each point from this category has to be translated to be centered. Check the code and demo posted below.
Code:
var today = new Date(),
day = 1000 * 60 * 60 * 24;
// Set to 00:00:00:000 today
today.setUTCHours(0);
today.setUTCMinutes(0);
today.setUTCSeconds(0);
today.setUTCMilliseconds(0);
today = today.getTime();
// THE CHART
Highcharts.ganttChart('container', {
chart: {
events: {
load: function() {
var chart = this,
series = chart.series[0];
series.points.forEach(function(point) {
point.graphic.translate(0, -25);
});
}
}
},
title: {
text: 'Grouping tasks vertically'
},
yAxis: {
categories: ['Resource 1', 'Resource 2', 'Resource 3'],
breaks: [{
breakSize: 0.5,
from: 0,
to: 0
}]
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
}
},
series: [{
name: 'Resource 1',
data: [{
name: 'Task A',
y: 0,
start: today - (2 * day),
end: today + (6 * day)
}, {
name: 'Task B',
y: 0.6,
start: today - (1 * day),
end: today + (6 * day),
color: 'rgba(140, 140, 140, 0.7)'
}, {
name: 'Task C',
y: 0,
start: today + (13 * day),
end: today + (17 * day)
}]
}, {
name: 'Resource 2',
data: [{
name: 'Task D',
y: 1,
start: today - (1 * day),
end: today + (6 * day)
}, {
name: 'Task E',
y: 1,
start: today + (7 * day),
end: today + (9 * day)
}, {
name: 'Task F',
y: 1,
start: today + (11 * day),
end: today + (12 * day)
}, {
name: 'Task G',
y: 1,
start: today + (14 * day),
end: today + (16 * day)
}]
}, {
name: 'Resource 3',
data: [{
name: 'Task H',
y: 2,
start: today - (1.5 * day),
end: today + (4 * day)
}, {
name: 'Task I',
y: 2,
start: today + (6 * day),
end: today + (9 * day)
}, {
name: 'Task J',
y: 2,
start: today + (10 * day),
end: today + (14 * day)
}, {
name: 'Task K',
y: 2,
start: today + (15 * day),
end: today + (17 * day)
}]
}]
});
#container {
max-width: 1000px;
min-width: 450px;
margin: 1em auto;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/gantt/modules/gantt.js"></script>
<script src="https://code.highcharts.com/gantt/modules/exporting.js"></script>
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/cdhxgurq/1/
API:
https://api.highcharts.com/gantt/yAxis.breaks
https://api.highcharts.com/class-reference/Highcharts.SVGElement#translate
Related
Highstock has a time range selector below the main graph that contains dates and times. For example 10. Oct in this example: https://www.highcharts.com/demo/stock/intraday-area
How can I format those, eg to say '10/10' instead?
As I understand you want to change the navigator date format, under the chart.
You can add "navigator" to your chart options like this;
navigator: {
xAxis: {
labels: {
formatter: function() {
var d = new Date(this.value),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2)
month = '0' + month;
if (day.length < 2)
day = '0' + day;
return [day,month,year].join('/');
}
}
}
}
You can find full code snippet below and change formatter function.
Highcharts.getJSON('https://cdn.jsdelivr.net/gh/highcharts/highcharts#v7.0.0/samples/data/new-intraday.json', function (data) {
// create the chart
Highcharts.stockChart('container', {
title: {
text: 'AAPL stock price by minute'
},
subtitle: {
text: 'Using ordinal X axis'
},
xAxis: {
gapGridLineWidth: 0
},
navigator: {
xAxis: {
labels: {
formatter: function() { // You can change the function according to your needs.
var d = new Date(this.value);
var month = '' + (d.getMonth() + 1);
var day = '' + d.getDate();
var year = d.getFullYear();
if (month.length < 2)
month = '0' + month;
if (day.length < 2)
day = '0' + day;
return [day,month].join('/');
}
}
}
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data: data,
gapSize: 5,
tooltip: {
valueDecimals: 2
},
fillColor: {
linearGradient: {
x1: 0,
y1: 0,
x2: 0,
y2: 1
},
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
threshold: null
}]
});
});
<div id="container" style="height: 400px; min-width: 310px"></div>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/data.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<script src="https://code.highcharts.com/stock/modules/export-data.js"></script>
How can I have collapsible sub-tasks while using the table on the left? If I remove the table columns then it works fine. This is the example from the official website, unfortunately there is no demo for my case. Any guidance is appreciated.
Here is the fiddle I've played with: https://jsfiddle.net/sharvadze/4h80gdts/1/
Highcharts.ganttChart('container', {
title: {
text: 'Left Axis as Table'
},
xAxis: {
tickPixelInterval: 70
},
yAxis: {
type: 'category',
grid: {
enabled: true,
borderColor: 'rgba(0,0,0,0.3)',
borderWidth: 1,
columns: [{
title: {
text: 'Project'
},
labels: {
format: '{point.name}'
}
}, {
title: {
text: 'Assignee'
},
labels: {
format: '{point.assignee}'
}
}, {
title: {
text: 'Est. days'
},
labels: {
formatter: function () {
var point = this.point,
days = (1000 * 60 * 60 * 24),
number = (point.x2 - point.x) / days;
return Math.round(number * 100) / 100;
}
}
}, {
labels: {
format: '{point.start:%e. %b}'
},
title: {
text: 'Start date'
}
}, {
title: {
text: 'End date'
},
offset: 30,
labels: {
format: '{point.end:%e. %b}'
}
}]
}
},
tooltip: {
xDateFormat: '%e %b %Y, %H:%M'
},
series: [{
name: 'Project 1',
data: [{
id: 'test',
start: Date.UTC(2017, 10, 18, 8),
end: Date.UTC(2017, 10, 25, 16),
name: 'Start prototype',
assignee: 'Richards',
y: 0
}, {
parent: 'test',
start: Date.UTC(2017, 10, 20, 8),
end: Date.UTC(2017, 10, 24, 16),
name: 'Develop',
assignee: 'Michaels',
y: 1
}, {
start: Date.UTC(2017, 10, 25, 16),
end: Date.UTC(2017, 10, 25, 16),
name: 'Prototype done',
assignee: 'Richards',
y: 2
}, {
start: Date.UTC(2017, 10, 27, 8),
end: Date.UTC(2017, 11, 3, 16),
name: 'Test prototype',
assignee: 'Richards',
y: 3
}, {
start: Date.UTC(2017, 10, 23, 8),
end: Date.UTC(2017, 11, 15, 16),
name: 'Run acceptance tests',
assignee: 'Halliburton',
y: 4
}]
}]
});
there's no data in load Event ( chart.series[0].data )
error code : Uncaught TypeError: Cannot read property 'open' of undefined
then put enabled:false like this..
ex)
dataGrouping: {
enabled: false
units: groupingUnits
},
it works, but too slow..
what should i do?
Here's my code:
$(document).ready(function(){
var area = {
chart:{
height:500,
marginRight:30,
backgroundColor:'#F4F4F4',
events: {
load: function() {
var chart = $('#container').highcharts();
var point = chart.series[0].data[chart.series[0].data.length -1];
text = chart.renderer.text(
'',
point.plotX + chart.plotLeft + 10,
point.plotY + chart.plotTop - 10
).attr({
zIndex: 5
}).add(),
box = text.getBBox();
chart.renderer.rect(box.x - 5, box.y - 5, box.width + 10, box.height + 10, 5)
.attr({
fill: '#FFFFEF',
stroke: 'gray',
'stroke-width': 1,
zIndex: 4
})
//.add();
series1 = this.series[0];
series2 = this.series[1];
//dataMax
var price = series1.data[series1.data.length -1].open;
refreshIntervalId = setInterval(function () {
var x = series1.data[series1.data.length -1].x; // current time
var time = (new Date).getTime();
var o = series1.data[series1.data.length -1].open;
var h = series1.data[series1.data.length -1].high;
var l = series1.data[series1.data.length -1].low;
if(time % 2 === 0){
price = o + Math.random() * 3;
}
else {
price = o - Math.random() * 3;
}
if(price > series1.data[series1.data.length -1].high){
h = price;
}
if(price < series1.data[series1.data.length -1].low){
l = price;
}
var c = price;
var y = series2.data[series2.data.length -1].y + Math.round(Math.random() * 1);
series1.data[series1.data.length -1].update({x : x, open : o, high: h, low: l, close: c}, true);
series2.data[series2.data.length -1].update({x : x, y: y}, false);
}, 1000);
}
}
},
credits: {
enabled:true,
position: { align: 'right', x: -10, verticalAlign: 'bottom', y: -5 },
style: { cursor: 'pointer', color: 'black', fontSize: '9px' }
},
scrollbar: {
enabled: false
},
rangeSelector: {
selected: 1,
inputEnabled: false
},
title: {
useHTML: true,
x: -10,
y: 8,
},
xAxis: {
gridLineWidth: 1,
labels: {
format: '{value:%m-%d}',//'{value:%Y-%m-%d}',
}
},
yAxis:[{
crosshair: {
snap: false
},
height: 200,
labels: {
align: 'right',
x: 25,
formatter: function (){
return $.number(Highcharts.numberFormat(this.value, 0,'',''));
}
},
},
/*volume*/
{
labels: {
align: 'right',
x: 20,
},
// lineWidth: 2
top: 280,
height: 113,
offset: 0,
}],
series: [{
type: 'candlestick',
name: 'AAPL Stock Price',
data: data,
dataGrouping: {
units: groupingUnits
},
point:{
events:{
mouseOver: function (){
var chart = this.series.chart;
if (!chart.lbl){
chart.lbl = chart.renderer.label('')
.attr({
padding: 10,
r: 10,
//fill: Highcharts.getOptions().colors[1]
})
.css({color: 'black'})
.add();
}//if OFF
var timeStamp = this.x,
date = new Date(parseFloat(timeStamp)),
currentTime = get_Date(date);
chart.lbl
.show()
.attr({
text: currentTime + ' H: ' + $.number(this.high) + ' L: ' + $.number(this.low) + ' O: ' + $.number(this.open) + ' C: ' + $.number(this.close),
y: 22,
});
},//mouseover OFF
mouseOut: function (){
if (this.series.chart.lbl){
this.series.chart.lbl.hide();
}//if OFF
}//mouseout OFF
},//events OFF
},//point OFF
}, //series[0] OFF
{
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
},
}]//series[1] OFF
}
var dataLength = data.length,
i = 0;
groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]];
for (i; i < dataLength; i += 1) {
candlestickOhlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
]);
}//for OFF
option = candlestick;
option.series[0].data = data;
$('#container').highcharts('StockChart', option);
});
I have been creating a Highstock chart and I am facing problem in fixing xAxis interval in date/time formatter code here according to live stock data on 30 minutes interval.
Here is the code of my chart:
Highcharts.setOptions({
global: {
timezoneOffset: 4 * 60
}
});
var dataObject = {
chart: {
renderTo: 'container',
defaultSeriesType: 'area',
width: '1280',
height: '640'
},
plotOptions: {
series: {
lineWidth: 1
}
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
second: '<br/>%H:%M:%S',
minute: '<br/>%H:%M:%S',
hour: '<br/>%H:%M:%S',
day: '%Y<br/>%b-%d',
week: '%Y<br/>%b-%d',
month: '%Y-%b',
year: '%Y'
},
tickPositions:['09:00:000','12:00:00','15:00:00','18:00:00']
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
min: minRange,
max: maxRange,
tickInterval: 0.5,
title: {
text: 'Last',
margin: 40
}
},
series: [{
name: 'AAPL',
fillColor : {
linearGradient : {
x1: 0,
y1: 0.8,
x2: 0,
y2: 0
},
stops : [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
data: [[1440161106000,112.65],[1440161931000,112.65],[1440162841000,112.65],[1440163745000,112.65],[1440164584000,111.41],[1440164704000,111.11],[1440165543000,111.51],[1440166443000,110.96],[1440167345000,110.66],[1440168183000,109.29],[1440168300000,109.5],[1440169144000,109.17],[1440170038000,108.29],[1440170945000,108.92],[1440171784000,108.48],[1440171904000,108.61],[1440172743000,108.81],[1440173640000,108.6],[1440174544000,107.72],[1440175385000,108.03],[1440175503000,107.99],[1440176338000,108],[1440177245000,108.24],[1440178143000,108.4],[1440178983000,108.28],[1440179104000,108.21],[1440179915000,108.2],[1440180844000,108.3],[1440181743000,108.06],[1440182585000,107.71],[1440182705000,107.51],[1440183543000,107.5],[1440184444000,106.53],[1440185345000,106.08],[1440186184000,106.61]] }]
};
chart = new Highcharts.StockChart(dataObject),function(chart){
$('#container').bind("mousewheel",function(event,delta){
var x = event.originalEvent.wheelDelta /120;
console.log(x);
if (delta > 0) {
var min = chart.xAxis[0].getExtremes().min,
max = chart.xAxis[0].getExtremes().max;
chart.xAxis[0].setExtremes((min + 12 * 3600 * 1000),(max - 12 * 3600 * 1000));
} else {
var min = chart.xAxis[0].getExtremes().min,
max = chart.xAxis[0].getExtremes().max;
chart.xAxis[0].setExtremes((min - 12 * 3600 * 1000),(max + 12 * 3600 * 1000));
}
});
};
JSFiddle : jsfiddle.net/zubairsultan/cvnzkv0s/5
You can fix minTickInterval to 3600000 so your xAxis will be "hourly based":
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
second: '<br/>%H:%M:%S',
minute: '<br/>%H:%M:%S',
hour: '<br/>%H:%M:%S',
day: '%Y<br/>%b-%d',
week: '%Y<br/>%b-%d',
month: '%Y-%b',
year: '%Y'
},
minTickInterval: 3600000
},
See your JSFiddle modified here: http://jsfiddle.net/cvnzkv0s/9/
Is that what you want ?
I am using the columnrange type from Highcharts-more.
The default data labels formatter puts the min / max data at both ends of the range, which is nice.
Is there a way to attach another label to each point? (for example : the data name, right in the middle of the bar)
Please see my work at:
JSFiddle
This is a family tree with life ranges.
I'd like to display the names shown in tooltips at the center of bars.
(FYI I tried to overload the chart with text using the renderer : it worked... but the texts were attached to the chart, not to the points, and zooming left them in place, while the points moved around. Is there maybe a way to attach text labels to the each point on the chart onLoad event?)
Thank you.
$(function () {
$('#container').highcharts({
chart: {
type: 'columnrange',
inverted: true,
marginLeft: 40,
zoomType: 'xy'
},
title: {
text: 'My family tree'
},
xAxis: {
labels: {
enabled: false
},
min: 0,
max: 10
},
yAxis: {
type: 'datetime',
min: new Date().setYear(1900).valueOf(),
max: new Date().valueOf(),
title: {
text: 'Year'
},
endOnTick: false
},
legend: {
enabled: false
},
plotOptions: {
columnrange: {
grouping: false,
pointPadding: 0,
dataLabels: {
enabled: true,
useHTML: true,
formatter: function () {
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.y).setHours(0, 0, 0, 0)) return '<span style="color:black">' + Highcharts.dateFormat('%Y', this.y) + '</span>';
else return '';
}
}
}
},
tooltip: {
headerFormat: '{series.name}<br/>',
formatter: function () {
var l = this.point.name + '<br/>' + Highcharts.dateFormat('%e/%m/%Y', this.point.low);
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.point.high).setHours(0, 0, 0, 0)) l += '<br/>' + Highcharts.dateFormat('%e/%m/%Y', this.point.high);
return l;
}
},
series: [{
color: 'rgb(100,100,255)',
pointWidth: 150,
data: [{
name: 'Yann B',
low: Date.UTC(1976, 1, 27),
high: new Date().valueOf(),
x: 1 * 10 / 2
}]
}, {
color: 'rgb(150,150,255)',
pointWidth: 70,
data: [{
name: 'Jean-Yves B',
low: Date.UTC(1947, 3, 26),
high: Date.UTC(2006, 2, 10),
x: 1 * 10 / 4
}, {
name: 'Josiane M',
low: Date.UTC(1946, 8, 21),
high: Date.UTC(1998, 11, 26),
x: 3 * 10 / 4
}]
}, {
color: 'rgb(200,200,255)',
pointWidth: 30,
data: [{
name: 'Guillaume B',
low: Date.UTC(1907, 7, 4),
high: Date.UTC(1988, 1, 11),
x: 1 * 10 / 8
}, {
name: 'Marie-Jeanne S',
low: Date.UTC(1911, 7, 17),
high: Date.UTC(1986, 2, 3),
x: 3 * 10 / 8
}, {
name: 'Joseph M',
low: Date.UTC(1921, 3, 11),
high: Date.UTC(1996, 4, 23),
x: 5 * 10 / 8
}, {
name: 'Marie K',
low: Date.UTC(1925, 4, 4),
high: new Date().valueOf(),
x: 7 * 10 / 8
}]
}]
});
});
The use of the "inside" propriety is indeed relevant here. But I had to bypass the bug inherent to its use (see comment to last answer).
Here is a piece of code that works for datalabels. There still is a zIndex issue with the tool tips, and I'll try to post a more complete solution soon.
http://jsfiddle.net/SineDie/TREwr/1/
dataLabels: {
inside: true,
enabled: true,
useHTML: true,
formatter: function () {
if (this.y === this.point.low) {
var l = '<div style="text-align:center;color:black;width:' + (this.point.plotLow - this.point.plotHigh) + 'px">'
+ Highcharts.dateFormat('%Y', this.point.low) + ' - '
+ this.point.name;
// to avoid marking as dead if still living...
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.point.high).setHours(0, 0, 0, 0))
l += ' - ' + Highcharts.dateFormat('%Y', this.point.high);
l += '</div>';
return l;
}
else return '';
}
}
I did some modifications on formatter funcution. set datalabels inside property true and attach datanames to point's high values.
dataLabels: {
inside:true,
enabled: true,
useHTML: true,
formatter: function () {
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.y).setHours(0, 0, 0, 0)) {
if (this.y == this.point.high){
return '<span style="color:black">' + Highcharts.dateFormat('%Y', this.y) +' - '+ this.point.name + '</span>';
}
return '<span style="color:black">' + Highcharts.dateFormat('%Y', this.y) + '</span>';
}
else return '';
}
}