Highcharts Gantt milestone series - highcharts

I'm new to Highcharts and have been experimenting with the Gantt chart type, unfortunately there isnt a whole heap of documentation around right now.
My requirement is quite basic, I need to plot multiple series of milestones in order to show slippage of different projects. I've used some example code I found online to start me off however I need to remove the blank ('My 1st Row') line between the series. see:-
https://jsfiddle.net/z86aq99g
var today = new Date(),
day = 1000 * 60 * 60 * 24;
var grey_OrigTargDate = '#A6A6A6';
var blue_Completed = '#2e75b6';
var green_Ontarget = '#00b050';
var yellow_OfftrackMinor = '#ffc000';
var red_OffTrackMajor = '#ff0000';
// 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.setOptions({
colors: ['#058DC7']
});
Highcharts.ganttChart('container', {
title: {
text: 'Gantt Chart Test'
},
xAxis: {
currentDateIndicator: true,
min: today - 3 * day,
max: today + 18 * day
},
series: [{
name: 'Test series',
data: [{
taskName: 'My 1st row',
id: 'r1',
start: today + 4.5 * day,
milestone: true,
color: grey_OrigTargDate
}, {
taskName: 'My 1st row',
id: 'r2',
start: today + 7.5 * day,
milestone: true,
color: green_Ontarget
}, {
taskName: 'My 2nd row',
id: 'r3',
start: today + 9.5 * day,
milestone: true,
color: blue_Completed
}, {
taskName: 'My 2nd row',
id: 'r4',
start: today + 11.5 * day,
milestone: true,
color: red_OffTrackMajor
}]
}]
});
I am trying to chart 2 milestones on each line. I know that the x range series chart could accomplish something similar but I'd much prefer to use the gantt option. I'd appreciate any help.

You can solve this problem by assigning categories to the Y-axis
yAxis: {
type: 'category',
categories: ['A', 'B'],
reversed: true,
},
In order for this to work you could change the taskName with y: 0 / y: 1. It will work if your taskName is identical to your category names, but using y: 0 is more dynamic if you were to change the categories.
Your code will look like this in the end:
var today = new Date(),
day = 1000 * 60 * 60 * 24;
var grey_OrigTargDate = '#A6A6A6';
var blue_Completed = '#2e75b6';
var green_Ontarget = '#00b050';
var yellow_OfftrackMinor = '#ffc000';
var red_OffTrackMajor = '#ff0000';
// 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.setOptions({
colors: ['#058DC7']
});
Highcharts.ganttChart('container', {
title: {
text: 'Gantt Chart Test'
},
xAxis: {
currentDateIndicator: true,
min: today - 3 * day,
max: today + 18 * day
},
yAxis: {
type: 'category',
categories: ['A', 'B'],
reversed: true,
},
series: [{
name: 'Test series',
data: [{
y: 0, // taskName: 'A' works too
id: 'r1',
start: today + 4.5 * day,
milestone: true,
color: grey_OrigTargDate
}, {
y: 0,
id: 'r2',
start: today + 7.5 * day,
milestone: true,
color: green_Ontarget
},{
y: 1,
id: 'r3',
start: today + 9.5 * day,
milestone: true,
color: blue_Completed
}, {
y: 1,
id: 'r4',
start: today + 11.5 * day,
milestone: true,
color: red_OffTrackMajor
}]
}]
});
Here is a working JSFiddle https://jsfiddle.net/z86aq99g/1/

Related

Kendo Gantt Timeline in 30 minute increments?

I am using the Kendo Gantt chart with ASP.NET Core MVC, and I would like to get the Day view timeline to show in 30 minute increments vs. 1 hour increments. The working hours I'm trying to display for each day are 7:00 AM to 3:30 PM, but I cannot get that 3:30 PM end of day to display.
Here is an example of getting a time header template using the jquery kendo gantt chart
<div id="gantt"></div>
<script>
$("#gantt").kendoGantt({
dataSource: [{
id: 1,
orderId: 0,
parentId: null,
title: "Task1",
start: new Date("2014/6/17 9:00"),
end: new Date("2014/6/17 11:00")
}],
views: [
{ type: "day", timeHeaderTemplate: kendo.template("#=kendo.toString(start, 'T')#") },
{ type: "week" },
{ type: "month" }
]
});
</script>
However, I can't figure out how get that template to show the 30 minute increments, or if there is a different way to accomplish this. Essentially, I want it to look like the Kendo Scheduler Timeline view shown here:
I opened a support ticket with Telerik and got an answer that while there is no built-in way to do this with the Gantt component, one way to implement would be to create a custom view as demonstrated here: https://docs.telerik.com/kendo-ui/controls/scheduling/gantt/how-to/creating-custom-view
Custom view example code:
<div id="gantt"></div>
<script type="text/javascript">
var gantt;
$(function StartingPoint() {
kendo.ui.GanttCustomView = kendo.ui.GanttView.extend({
name: "custom",
options: {
yearHeaderTemplate: kendo.template("#=kendo.toString(start, 'yyyy')#"),
quarterHeaderTemplate: kendo.template("# return ['Q1', 'Q2', 'Q3', 'Q4'][start.getMonth() / 3] #"),
monthHeaderTemplate: kendo.template("#=kendo.toString(start, 'MMM')#")
},
range: function(range) {
this.start = new Date("01/01/2013");
this.end = new Date("01/01/2016");
},
_generateSlots: function(incrementCallback, span) {
var slots = [];
var slotStart = new Date(this.start);
var slotEnd;
while (slotStart < this.end) {
slotEnd = new Date(slotStart);
incrementCallback(slotEnd);
slots.push({ start: slotStart, end: slotEnd, span: span });
slotStart = slotEnd;
}
return slots;
},
_createSlots: function() {
var slots = [];
slots.push(this._generateSlots(function(date) { date.setFullYear(date.getFullYear() + 1); }, 12));
slots.push(this._generateSlots(function(date) { date.setMonth(date.getMonth() + 3); }, 3));
slots.push(this._generateSlots(function(date) { date.setMonth(date.getMonth() + 1); }, 1));
return slots;
},
_layout: function() {
var rows = [];
var options = this.options;
rows.push(this._slotHeaders(this._slots[0], kendo.template(options.yearHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[1], kendo.template(options.quarterHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[2], kendo.template(options.monthHeaderTemplate)));
return rows;
}
});
gantt = new kendo.ui.Gantt($("#gantt"),
$.extend({
columns: [
{ field: "id", title: "ID", sortable: true, editable: false, width: 30 },
{ field: "title", title: "Title", sortable: true, editable: true, width: 100 },
{ field: "start", title: "Start Time", sortable: true, editable: true, format: "{0:MM/dd/yyyy HH:mm}", width: 100 },
{ field: "end", title: "End Time", sortable: true, editable: true, format: "{0:MM/dd/yyyy HH:mm}", width: 100 }
],
views: [
"week",
{ type: "kendo.ui.GanttCustomView", title: "Quaterly", selected: true }
],
listWidth: 500,
dataBound: function() {
var height = this.timeline.view().header.height();
this.list.thead.find('tr').css('height',height);
},
dataSource: {
data: [{ id: 1, parentId: null, percentComplete: 0.2, orderId: 0, title: "foo", start: new Date("05/05/2014 09:00"), end: new Date("06/06/2014 10:00") },
{ id: 2, parentId: null, percentComplete: 0.4, orderId: 1, title: "bar", start: new Date("07/06/2014 12:00"), end: new Date("08/07/2014 13:00") }]
},
dependencies: {
data: [
{ id: 1, predecessorId: 1, successorId: 2, type: 1 }
]
}
}, {})
);
});
</script>

Highcharts - Performance issue using chart with x values date and TIME

I am plotting a chart with ‘y’ axis being numeric values and ‘x’ axis being date time values.
I was able to process a JSON object of 3000 items. However, because of our business rules, we also need to display the time: hours + minutes in the chart’s tooltips.
This changed everything!
Now the chart takes about 15 seconds to plot 2000 records. This is unacceptable.
I can see clearly that when I remove the time part of my Date object the charts works perfectly. It is just when added the hours and minutes that performance gets affected.
Trying different things I realized that your charts should support the amount of data I am using since it is not massive.
We love the charts but performance is key for us to continue using your products.
Can you help me with this issue?
Please check this fiddle so you can understand my problem. Feel free to remove the hours and minutes variables from the DateUtc creation:
https://jsfiddle.net/17a3jry9/7/
Thanks in advance!
var pointStart = new Date();
var data = [{"date":"2017-11-08","time":"1712","perc":10},{"date":"2017-11-08","time":"1608","perc":10},{"date":"2017-11-08","time":"1506","perc":10},{"date":"2017-11-08","time":"1408","perc":10},{"date":"2017-11-08","time":"1309","perc":10},{"date":"2017-11-08","time":"1207","perc":10},{"date":"2017-11-08","time":"1110","perc":10},{"date":"2017-11-08","time":"1003","perc":10},{"date":"2017-11-08","time":"0910","perc":10},{"date":"2017-11-08","time":"0810","perc":10},{"date":"2017-11-08","time":"0708","perc":10},{"date":"2017-11-09","time":"1710","perc":10},{"date":"2017-11-09","time":"1604","perc":10},{"date":"2017-11-09","time":"1510","perc":10},{"date":"2017-11-09","time":"1406","perc":10},{"date":"2017-11-09","time":"1310","perc":10},{"date":"2017-11-09","time":"1205","perc":10},{"date":"2017-11-09","time":"1107","perc":10},{"date":"2017-11-09","time":"1010","perc":10},{"date":"2017-11-09","time":"0912","perc":10},{"date":"2017-11-09","time":"0806","perc":10}{"date":"2018-10-25","time":"0709","perc":10},{"date":"2018-10-25","time":"1009","perc":10},{"date":"2018-10-25","time":"1208","perc":10},{"date":"2018-10-25","time":"1309","perc":10},{"date":"2018-10-25","time":"1410","perc":10},{"date":"2018-10-25","time":"1510","perc":10},{"date":"2018-10-25","time":"1702","perc":10},{"date":"2018-10-26","time":"1409","perc":10},{"date":"2018-10-26","time":"0710","perc":10},{"date":"2018-10-26","time":"1505","perc":10},{"date":"2018-10-26","time":"1704","perc":10},{"date":"2018-10-29","time":"0708","perc":10},{"date":"2018-10-29","time":"1007","perc":10},{"date":"2018-10-29","time":"1208","perc":10},{"date":"2018-10-29","time":"1406","perc":10},{"date":"2018-10-29","time":"1509","perc":10},{"date":"2018-10-29","time":"1610","perc":10},{"date":"2018-10-30","time":"0710","perc":10},{"date":"2018-10-30","time":"1010","perc":10},{"date":"2018-10-30","time":"1207","perc":10},{"date":"2018-10-30","time":"1409","perc":10},{"date":"2018-10-30","time":"1510","perc":10},{"date":"2018-10-30","time":"1709","perc":10},{"date":"2018-10-31","time":"0708","perc":10},{"date":"2018-10-31","time":"1009","perc":10},{"date":"2018-10-31","time":"1206","perc":10},{"date":"2018-10-31","time":"1409","perc":10},{"date":"2018-10-31","time":"1509","perc":10},{"date":"2018-10-31","time":"1708","perc":10},{"date":"2018-11-01","time":"0707","perc":10},{"date":"2018-11-01","time":"1007","perc":10},{"date":"2018-11-01","time":"1108","perc":10},{"date":"2018-11-01","time":"1250","perc":10},{"date":"2018-11-01","time":"1509","perc":10},{"date":"2018-11-01","time":"1407","perc":10},{"date":"2018-11-01","time":"1709","perc":10},{"date":"2018-11-02","time":"0708","perc":10},{"date":"2018-11-02","time":"1007","perc":10},{"date":"2018-11-02","time":"1108","perc":10},{"date":"2018-11-02","time":"1210","perc":10},{"date":"2018-11-02","time":"1407","perc":10},{"date":"2018-11-02","time":"1509","perc":10},{"date":"2018-11-02","time":"1608","perc":10},{"date":"2018-11-02","time":"1715","perc":10},{"date":"2018-11-05","time":"0707","perc":10},{"date":"2018-11-05","time":"1007","perc":10},{"date":"2018-11-05","time":"1209","perc":10},{"date":"2018-11-05","time":"1408","perc":10},{"date":"2018-11-05","time":"1509","perc":10},{"date":"2018-11-05","time":"1611","perc":10},{"date":"2018-11-05","time":"1715","perc":10},{"date":"2018-11-06","time":"0708","perc":10},{"date":"2018-11-06","time":"1007","perc":10},{"date":"2018-11-06","time":"1201","perc":10},{"date":"2018-11-06","time":"1410","perc":10},{"date":"2018-11-06","time":"1510","perc":10},{"date":"2018-11-06","time":"1709","perc":10},{"date":"2018-11-07","time":"0708","perc":10},{"date":"2018-11-07","time":"1007","perc":10},{"date":"2018-11-07","time":"1209","perc":10},{"date":"2018-11-07","time":"1307","perc":10},{"date":"2018-11-07","time":"1410","perc":10},{"date":"2018-11-07","time":"1506","perc":10},{"date":"2018-11-07","time":"1708","perc":10},{"date":"2018-11-08","time":"0707","perc":10},{"date":"2018-11-08","time":"1009","perc":10},{"date":"2018-11-08","time":"1207","perc":10},{"date":"2018-11-08","time":"1309","perc":10},{"date":"2018-11-08","time":"1412","perc":10},{"date":"2018-11-08","time":"1508","perc":10}];
var newSeries = data.map(function (key) {
var utilDate = new Date(key.date);
var hours = parseInt(key.time.slice(0, 2));
var minutes = parseInt(key.time.slice(2, 4));
return { x: Date.UTC(utilDate.getFullYear(), utilDate.getMonth(), utilDate.getDate(), hours, minutes), y: key.perc, key: key.id };
});
Highcharts.stockChart('container', {
xAxis: {
type: 'datetime',
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Util (%)'
},
min: 0
},
tooltip: {
headerFormat: '<b>{point.x: %A, %b %e, %I:%M %p}</b><br>'
//pointFormat: '{point.x:%e. %b}: {point.y:.2f} m'
},
colors: ['teal', 'red'],
// Define the data points. All series have a dummy year
// of 1970/71 in order to be compared on the same x axis. Note
// that in JavaScript, months start at 0 for January, 1 for February etc.
series: [{
name: "Util",
data: newSeries
}],
title: {
text: 'Util Movement'
},
subtitle: {
text: ""
},
plotOptions: {
series: {
cursor: 'pointer',
turboThreshold: 10000,
point: {
events: {
}
},
label: {
connectorAllowed: false
},
pointStart: pointStart.getFullYear()
}
},
responsive: {
rules: [{
condition: {
maxWidth: 200
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
});
Please take a look to the browser console, you have information there about error: Highcharts error #15: www.highcharts.com/errors/15.
This means that you have unsorted data, so you need to sort them:
newSeries.sort(function(a, b){
return a.x - b.x
});
Live demo: https://jsfiddle.net/BlackLabel/onq0Lurx/

highstock charts - button for date range

in my application I use angular Highstock for charts. I have a lot of data (many millions), and now i want to put the existing buttons for set date range (1week, 1 month, 3 months, 1year, all), but also to click on any button to send a new request to the server to not accumulating data. Example, if pressed button "one week", that only the server retrieves the data for one week, if you click on a button to one month, to take data for a single month. I do not want to call unnecessary data, and that the server slows down, if I'm looking for data for one month, and the server comes back to me all data. Here is the code. Thanks in advance
> https://jsfiddle.net/tf7pr1ft/
Thnx to #Grzegorz Blachliński i fix this. here is code
$scope.chartConfig1 = {
xAxis: {
ordinal: false,
//za dodat date range postavit events i range selectors
events : {
afterSetExtremes: getDateRange //here i add my custom function
}
},
yAxis: {
plotLines: [{
color: '#FF0000',
width: 1,
value: 11.50,
label: {text: '11.50'}
}]
},
options: {
chart: {
zoomType: 'x',
backgroundColor: 'rgba(255, 255, 255, 1)',
polar: true,
type: 'line',
borderRadius: 5
},
legend: {
enabled: true
},
rangeSelector: {
selected : 0, //here i defined default range
enabled: true,
inputStyle: {
color: 'black'
}
},
navigator: {
enabled: true
}
},
series: [],
title: {
text: 'Solar and Battery voltage average'
},
useHighStocks: true
},
$scope.chartConfig1.series.push({
id: 1,
name: "Solar voltage average",
data: $scope.data[0],
tooltip: {
valueDecimals: 2
}
},   {
id: 2,
name: "Battery voltage average",
data: $scope.data[1],
tooltip: {
valueDecimals: 2
}
}
);
and here is my custom function
getDateRange = function (e) {
var date1 = new Date(e.min);
var date2 = new Date(e.max);
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
$http.get(serviceBase + 'aaaaa/aaaaaa/' + $stateParams.klupaID + '/aaaaaaa?days=' + diffDays, function(data){
//ukoliko buden dodavat još koji config obavezno dodat broj koliko ih ima na i<=8
for (i=1; i<=8; i++){
$scope.chartConfigString = 'chartConfig' + i;
$scope.chartConfigString.series[0].setData(data);
$scope.chartConfigString.hideLoading();
}
});
};
Now i have another problems, i want to have four selectors (buttons), 1months, 3months, 1year and ALL. I set default range, when open app, on 1month, and here is problem. Buttons for another range is disabled, beacause i get data from url only for one month. I want to have enabled all buttons for select any range. Thnx

Highcharts datagrouped updating column lose visible integrity

In a project, I'm using something very similar to this fiddle: http://jsfiddle.net/Z3vhg/
The code for this dynamically updating data-grouped columns chart is the following:
$('#container').highcharts('StockChart', {
chart : {
type: 'column',
events : {
load : function() {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
}, 1000);
}
}
},
yAxis: {
offset: 30
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 2
},
title : {
text : 'Live random data'
},
exporting: {
enabled: false
},
series : [{
name : 'Random data',
dataGrouping: {
groupPixelWidth: 60
},
data : (function() {
// generate an array of random data
var data = [], time = (new Date()).getTime(), i;
for( i = -999; i <= 0; i++) {
data.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data;
})()
}]
});
The problem can be observed in the fiddle above: as the data updates and adds new points, the first point on the x axis is shifted, but since data grouping is used, the column remains there but gives the impression that the first column value is actually changing...
Any help appreciated, as it may be a weird combination issue.

Highstock Issue - Can't draw and plot chart correctly

I'm working on project to display stock information using Highstock.
Question 1:
I tried to display ohlc data using ohlc graph, high and low using areasplinerange graph, and volume using column chart.
Everything works fine, if i zoom 1m, 3m, 6m, YTD, and 1y. Here is the snapshot. link1. But if zoom to All, The graph messed up like this link2.
Am i wrong in my coding or it's bug?
Question 2:
In the same chart, I have code to change the type of graph from ohlc to line. It works fine when I zoom to 1m, 3m. Here is the snapshot link3. But it show me no line chart when i zoom to 6m, 1y, and All. Here is the snapshot link4.
How can this happen?
Thank you for your help.
The Code:
Here is the code that i used to display the chart
$.getJSON(url, function (data1) {
$.getJSON(urlprediction, function (data2) {
var ohlc = [],
volume = [],
closed = [],
forecast = [],
dataLength1 = data1.length;
dataLength2 = data2.length;
for (i = 0; i < dataLength1; i++) {
ohlc.push([
data1[i][0], // the date
data1[i][1], // open
data1[i][2], // high
data1[i][3], // low
data1[i][4] // close
]);
closed.push([
data1[i][0], // the date
data1[i][4] // close
]);
volume.push([
data1[i][0], // the date
data1[i][5] // the volume
])
}
for (i = 0; i < dataLength2; i++) {
forecast.push([
data1[i][0], // the date
data1[i][1],
data1[i][2], // close
])
}
// set the allowed units for data grouping
var groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]];
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: title
},
yAxis: [{
title: {
text: 'OHLC'
},
height: 360,
lineWidth: 2
}, {
title: {
text: 'Volume'
},
top: 433,
height: 100,
offset: 0,
lineWidth: 2
}],
series: [{
type: 'ohlc',
name: stockname,
data: ohlc,
}, {
type: 'areasplinerange',
name: stockname,
data: data2,
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
}]
});
});
});

Resources