We are trying to emulate a stepped area chart with Kendo UI to denote the direction/position in which an actuator travels over a period of time (+1 denoting clockwise, -1 denoting a counter-clockwise direction) during the course of a day. The period of time over which the actuator completes its transition is not constant.
The code is included below (alternatively please feel free to use the following jsfiddle at http://jsfiddle.net/pirahawk/XT6CZ/15/ to avoid any setup). We have used the Kendo Stockchart because it provides a complementary navigator component which allows the user to restrict the graph to a desired time period. However we are finding oddities in the chart api especially when the data set has large time lapses. As shown in the example below, we started off with receiving inputs that have 1 second intervals between them. Plotting these on the chart achieves the shape that we expect to see. However adding additional datapoints that are now apart by a few hours (please uncomment the data points shown), we are finding that the chart api seems to somehow incorrectly extrapolate the earlier data points.
When using the navigator to restrict the chart to the earlier period (between 2am - 2:30am), we do once again achieve the original shape. However we would like to have the same shape shown without having to do this (i.e. stop the api from extrapolating data points with large intervals between data points). Any help, advise on this issue would be greatly appreciated
var dataForSource = [{
date: new Date("December 16, 2013 02:06:00 AM"),
Count: 0
}, {
date: new Date("December 16, 2013 02:07:00 AM"),
Count: 1
},
{
date: new Date("December 16, 2013 02:09:00 AM"),
Count: 0
}, {
date: new Date("December 16, 2013 02:09:15 AM"),
Count: -1
},
{
date: new Date("December 16, 2013 02:09:45 AM"),
Count: 0
},
{
date: new Date("December 16, 2013 02:10:00 AM"),
Count: -1
}, {
date: new Date("December 16, 2013 02:15:00 AM"),
Count: 0
}
//Uncomment these out to see issue
/*
, {
date: new Date("December 16, 2013 04:10:01 PM"),
Count: -1
}
, {
date: new Date("December 16, 2013 11:55:00 PM"),
Count: 0
} */
];
var staticDataSource = new kendo.data.DataSource({
type: "line",
data: dataForSource
});
function createChart() {
$("#chart").kendoStockChart({
dataSource: staticDataSource,
dateField: "date",
series: [{
type: "line",
style: 'step',
//missingValues: "interpolate",
field: "Count",
categoryField: "date"
}],
xAxis: {
baseUnit: "seconds"
},
navigator: {
series: {
type: "line",
style: 'step',
field: "Count"
},
xAxis: {
baseUnit: "hours"
},
}
});
};
$(document).ready(createChart);
First of all, you're using wrong baseUnit in your example. It's property of categoryAxis not xAxis and seems to does not work in here.
You need to choose what do you wanna show in your chart, when you show long time period, by default data is aggregate to show in group which you define in baseUnit property. To "turn it off" you should set it for smallest available option: minutes. Now you gonna have all data points in your chart, but it's look even worse, just peek in JSFiddle what I prepared for you for see what i mean: http://jsfiddle.net/XT6CZ/18/
Regards
Related
Currently, my graph looks as below.
I am trying to change it to Sep 7, if the hour is 24 hours or 00:00.
I tried different formats like
format:'{value:%H:%M}',
or
format:'{value:%H:%M %e %b}',
But not getting the desired result. Could you suggest me what format I should use to make it work?
I was able to resolve this by using the following format.
xAxis: {
type: 'datetime',
opposite: true,
tickPosition: 'inside',
crosshair,
labels: {
y: -8,
},
dateTimeLabelFormats : {
day: '%b. %e',
hour: '%H:%M',
}
},
Now new graph looks like as below.
I'm trying to have a gantt chart with all 12 months in it. I'm doing this by setting the from & to values to currentDate.clone().endOf('year') & currentDate.clone().endOf('year'). But the gantt chart stopping appearing when setting these values, if I print out the dates they are valid & weirdly if I change the values to startOf('week') & endOf('week)` it renders the chart fine. Is this possible to do?
Package I'm using: https://github.com/ANovokmet/svelte-gantt
Edit:
My code is based on this index.js file: https://github.com/ANovokmet/svelte-gantt/blob/gh-pages/index.js
It might be simpler to ask, how can I modify it to show months instead of hours/days?
function time(input) {
return moment(input, "MMMM DD YYYY");
}
const currentStart = time(responseData.currentDate);
const currentEnd = time(responseData.currentDate);
gantt.$set({
fitWidth: false,
columnUnit: 'month',
rowPadding: 6,
rowHeight: 52,
columnOffset: 28.8,
magnetOffset: 15,
from: currentStart.clone().startOf('year'),
to: currentStart.clone().endOf('year'),
minWidth: 800,
headers: [{ unit: 'month', format: 'MMMM YYYY' }, { unit: 'day', format: 'ddd DD' }]
});
TL;DR:
Svelte Gantt Year + Months example
(note: svelte-gantt behavior is a bit finicky in the REPL, you might have to resize the width of the render panel to display the default 10 rows/tasks).
Important Update
I have noticed that there is an issue in the months' column headers, with January and May being repeated, February being skipped, and ultimately a one-month offset from May onwards (causing December to disappear as well). This is because of the way svelte-gantt handles month duration internally: all months are set to 30 days (!!). You can see this in this source file at line 118. The author even commented that this was incorrect...
Knowing this, you might want to reconsider using this module for an accurate representation of a yearly/monthly Gantt diagram, unless you fork the project and implement a correct handling of variable month durations yourself!
How I got there
I used the svelte-gantt large dataset demo source as a starting point, removing the GanttOptions import and component (irrelevant for this question). What I was left with was a Gantt diagram for a single day, hourly columns, and 100 generated rows & tasks (which I shortened to 10). The key info there was obviously the options object passed to the SvelteGantt constructor as props:
let options = {
dateAdapter: new MomentSvelteGanttDateAdapter(moment),
rows: data.rows,
tasks: data.tasks,
timeRanges,
columnOffset: 15,
magnetOffset: 15,
rowHeight: 52,
rowPadding: 6,
headers: [{ unit: 'day', format: 'MMMM Do' }, { unit: 'hour', format: 'H:mm' }],
fitWidth: true,
minWidth: 800,
from: currentStart,
to: currentEnd,
tableHeaders: [{ title: 'Label', property: 'label', width: 140, type: 'tree' }],
tableWidth: 240,
ganttTableModules: [SvelteGanttTable]
}
The changes needed to get from a single day diagram with hourly columns to a single year diagram with monthly columns were quite straightforward.
I removed the timeRanges option (which was used to set lunch & dinner time ranges in the daily diagram but were no longer useful in the yearly diagram - although you might want to use them again for bank holidays, or summer vacation periods for instance), and the associated data.
Then I added the columnUnit option, setting it to 'month', and changed the columnOffset option, setting it to 1, in order to have 1 column per month.
Finally I adjusted the headers option to display the year in the top line, and the abbreviated months in the second line (column headers): headers: [{ unit: 'year', format: 'YYYY' }, { unit: 'month', format: 'MMM' }].
The final, modified options object:
let options = {
dateAdapter: new MomentSvelteGanttDateAdapter(moment),
rows: data.rows,
tasks: data.tasks,
columnUnit: 'month',
columnOffset: 1,
magnetOffset: 15,
rowHeight: 52,
rowPadding: 6,
headers: [{ unit: 'year', format: 'YYYY' }, { unit: 'month', format: 'MMM' }],
fitWidth: true,
minWidth: 800,
from: currentStart,
to: currentEnd,
tableHeaders: [{ title: 'Label', property: 'label', width: 140, type: 'tree' }],
tableWidth: 240,
ganttTableModules: [SvelteGanttTable]
}
I then modified the currentStart and currentEnd values to reflect the new range of the diagram (a full year) by setting them to the beginning and the end of the current year, repectively:
const currentStart = moment().clone().startOf('year');
const currentEnd = moment().clone().endOf('year');
Finally, I had to modify the task generation process in order to randomly generate tasks that were meaningful enough for the new scale/range of the diagram:
// start of task (random day (1-20) + month (1-12))
const rand_d = (Math.random() * 20) | 0 + 1
const rand_m = (Math.random() * 12) | 0 + 1
const from = moment(`${rand_d} ${rand_m}`, 'D M')
// duration of task (random, 5 to 60 days)
const rand_l = (Math.random() * 55) | 0 + 5
const to = from.clone().add(rand_l, 'days')
tasks.push({
type: 'task',
id: ids[i],
resourceId: i,
label: 'Task #' + ids[i],
from,
to,
classes: colors[(Math.random() * colors.length) | 0],
generation
});
As a final cleanup, since by now I was no longer using the time() utility function, relying entirely on moment instead, I also removed the import { time } from '../utils'; statement.
I have been trying to replicate an ADCP Graph using the Heatmap chart by Highcharts but I am finding difficulties in changing the x-axis format.
Example of an ADCP Graph
How do i replicate the x-axis as shown in the example above?
I am also hoping for the format to be date(dd/mm/yyyy), time(00:00), depth(m), velocity(m/s) in the small popup that appears as you hover around the graph.
Here's a link to my code:
https://jsfiddle.net/6hzq3o12/6/
xAxis: {
type: 'datetime',
min: Date.UTC(2017, 0, 1),
max: Date.UTC(2017, 11, 31, 23, 59, 59),
labels: {
align: 'left',
x: 5,
y: 14,
format: '{value:%B}' // long month
},
showLastLabel: false,
tickLength: 16
}
To achieve expected effect you need to define your own xAxis.labels.formatter function, which recognizes labels on first, middle and last position, and then set its value format to DD/MM/YY. Otherwise (for all other labels) return the HH:MM value:
xAxis: {
type: 'datetime',
min: Date.UTC(2017, 0, 1),
max: Date.UTC(2017, 11, 31, 23, 59, 59),
labels: {
formatter: function() {
var timestamp = this.value
var ticks = this.axis.tickPositions
var isMiddle = ticks.length % 2 && ticks.indexOf(this.value) === Math.floor(ticks.length / 2)
var labelFormat
labelFormat = this.isFirst || this.isLast || isMiddle ? '%d/%m/%y' : '%H:%M'
return Highcharts.dateFormat(labelFormat, timestamp)
}
},
tickLength: 16
}
However, in order to make it work correctly, you need to provide the chart with appropriate data (with hours), as #ewolden says in his comment below your main post.
Live example: https://jsfiddle.net/25cwrqen/
I am using angular-google-chart and angularjs to display charts.
https://github.com/angular-google-chart/angular-google-chart
I have a set of data consisting of 100 data points in json which looks like this;
[{
value: 400,
time: "2014-05-07 13:51:39"
},
{
value: 425.28,
time: "2014-05-04 16:19:58"
},
{
value: 425.6,
time: "2014-05-03 16:19:56"
},
// rest of samples fall before 2014-05-04 time range
]
The problem is that on the Google Chart, it only shows the first 2 samples because for some reason, the chart only shows samples of past recent 3 days.
Here is the relevant javascript code for configuring Google Chart options.
var google_chart_options =
{
'hAxis': {
'title': "Date",
'format': "dd-MMM-yyyy HH:mm:ss",
},
};
var horizontal_axis = {id: "t", label: "Date", type: "datetime"};
var vertical_axis= {id: "s", label: "value", type: "number"};
var type = 'LineChart';
I have some questions;
What options should I use to get Google Chart to display data points of past X days or X number of data points?
What options should I use to get Google Chart to display data points from, say, 2014-05-01 16:30 to 2014-05-07 13:30?
I will answer your 2nd question.
What options should I use to get Google Chart to display data points
from, say, 2014-05-01 16:30 to 2014-05-07 13:30?
Here is the code.
var google_chart_options =
{
'hAxis': {
'title': "Date",
'format': "dd-MMM-yyyy HH:mm:ss",
viewWindow: {
min: new Date(2014, 4, 1, 16, 30), //note that month lies from 0 to 11 (December)
max: new Date(2014, 4, 7, 13, 30),
},
}
};
The key lies in the viewWindow options under hAxis.
I am trying to pass the dates to the Navigator, but by default the timestamp is passing to the navigator could any one please help me how to pass the dates to the navigator, i.e. as per dates that are there in x-axis.
this is the jsfiddle link : `http://jsfiddle.net/hj22wbe5/16/`
please find the jsfiddle.
Thanks
Why are you not sending in your data as time/value? This way navigator does this for you automatically? You have an array of strings for dates that you then parse in the xAxis.label function to display text - but your time in the data series is an integer starting from 0. Then you want to send in this modified date stamp into your navigator as a string? And you have duplicate values in your dates array. You are making much more work for yourself.
Send in data like below with your x as Date.UTC():
series: [{
name: 'RNA',
data: [{
x: Date.UTC(2014, 5, 14),
y: 99.43,
extprop: 'power issue'
}, {
x: Date.UTC(2014, 5, 19),
y: 99.40,
extprop: 'flood'
}...
See update jsFiddle demo. I assume you meant the time to go up without duplicates.
You can refer to navigator xaxis and use the same formatter, but better is using datetime type of xAxis as wergeld suggested.
navigator: {
enabled: true,
xAxis: {
labels: {
rotation: 90,
align: "left",
formatter: function () {
return dates[this.value];
},
},
tickInterval: 1
},
},
http://jsfiddle.net/hj22wbe5/18/