-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Timeseries scale #4364
Timeseries scale #4364
Conversation
@IlyaBeliaev I haven't had a chance to look at this in detail yet, but could you rebase this against master? |
<script src="../../../dist/Chart.js"></script> | ||
<script src="../../utils.js"></script> | ||
<style> | ||
canvas { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there's some indentation here that should be switched from spaces to tabs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
samples/scales/timeseries/line.html
Outdated
<script src="../../../dist/Chart.js"></script> | ||
<script src="../../utils.js"></script> | ||
<style> | ||
canvas { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spaces vs tabs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
src/scales/scale.timeseries.js
Outdated
allTimestamps = allTimestamps.concat(value); | ||
}); | ||
|
||
allTimestamps = arrayUnique(allTimestamps).sort(function(a, b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we should sort here. I would expect the user to pass the data points in sorted already. If they want to plot in reverse chronological order we should probably let them do that, but sorting would stop that from working
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, we shouldn't sort since.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we should add some config option to allow users to make reverse order. I can't build ticks without sorting here. Because there are a data from all datasets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe for the time series scale we can just say that scatter is not supported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'm fine saying scatter is not supported
docs/axes/cartesian/timeseries.md
Outdated
|
||
## Date Formats | ||
|
||
When providing data for the time scale, Chart.js supports all of the formats that Moment.js accepts. See [Moment.js docs](http://momentjs.com/docs/#/parsing/) for details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"time scale" -> "timeseries scale"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
docs/axes/cartesian/timeseries.md
Outdated
data: data, | ||
options: { | ||
scales: { | ||
xAxes: [{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should add the type
option here to the x axis config
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/scales/scale.timebase.js
Outdated
// Get tooltip label | ||
getLabelForIndex: function(index, datasetIndex) { | ||
var me = this; | ||
var label = me.chart.data.labels && index < me.chart.data.labels.length ? me.chart.data.labels[index] : ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] me.chart.data
is used a couple of times here. I think we should capture it in a local variable for improved minification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
time: { | ||
parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment | ||
format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to provide this option since it's deprecated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, It looks like both options have no effect on time series. So I can remove them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Format is used in helpers.time and it should be removed from both scales at one time.
src/scales/scale.timeseries.js
Outdated
format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/ | ||
unit: false, // false == automatic or override with week, month, year, etc. | ||
round: false, // none, or override with week, month, year, etc. | ||
displayFormat: false, // DEPRECATED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same with this option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed.
return value; | ||
}, | ||
getBasePixel: function() { | ||
return this.bottom; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what will this do for horizontal bar charts using the timeseries axis as the y axis?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works only on x axis same as time scale.
23d57fd
to
6b9c919
Compare
I think this is ready to be merged (other than the conflict in |
7c66743
to
99ee03c
Compare
it's good! made rebase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few feedback.
Wondering if since timeseries
is closer to the category
logic, why not inheriting category
instead of timebase
, and have time manipulation method as helpers?
docs/axes/cartesian/timeseries.md
Outdated
@@ -0,0 +1,94 @@ | |||
# TimeSeries Cartesian Axis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we find a way to avoid this doc duplication: maybe merge both in the same page (docs/axes/cartesian/time.md
) with a special section about the TimeSeries
listing differences? or a common page for time base scales?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added timeseries description into time.md
samples/samples.js
Outdated
@@ -117,6 +117,18 @@ | |||
path: 'scales/time/combo.html' | |||
}] | |||
}, { | |||
title: 'TimeSeries scale', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need to duplicate the 3 examples, maybe 1 is enough and could be added to the Time Scale
group at the end (title: Series (TimeSeries Scale)
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A single example would be fine with me. I would just suggest that we not use the combo chart as the example in that case. We were also talking about following up afterwards in a separate PR with some improvements to the time samples. E.g. make the samples show more points by default and add a dropdown which lets you see samples with minutes, hours, weeks, months, etc. instead of just days
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/scales/scale.timebase.js
Outdated
|
||
return label; | ||
}, | ||
// Function to format an individual tick mark |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation++
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/scales/scale.timebase.js
Outdated
var label = chartData.labels && index < chartData.labels.length ? chartData.labels[index] : ''; | ||
var value = chartData.datasets[datasetIndex].data[index]; | ||
|
||
if (value !== null && typeof value === 'object') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if(helpers.isObject(value))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/scales/scale.timebase.js
Outdated
|
||
var callback = helpers.valueOrDefault(tickOpts.callback, tickOpts.userCallback); | ||
|
||
if (callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return {
value: callback? callback(formattedTick, index, ticks) : formattedTick,
major: major
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/scales/scale.timebase.js
Outdated
convertTicksToLabels: function() { | ||
var me = this; | ||
me.ticksAsTimestamps = me.ticks; | ||
me.ticks = me.ticks.map(function(tick) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
me.ticks = me.ticks.map(moment).map(me.tickFormatFunction, me);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not possible here because moment has constructor with multiple params. See https://momentjs.com/docs/#/parsing/string-formats/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to add a comment or even better, change it for a vanilla for loop and avoid doubling function calls?
getLabelCapacity: function(exampleTime) { | ||
var me = this; | ||
|
||
me.displayFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move that line after all var to help minification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
me.displayFormat used inside me.tickFormatFunction which is called on a next line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not obvious :\
minUnit: 'millisecond', | ||
|
||
// defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/ | ||
displayFormats: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should really find a way to avoid these options duplication (not sure how though) since both scales inherit the same base time scale, so would make sense to have common options in the base class as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now time and timeseries scale has different displayFormats because timeseries scale does not support tick alignment and major units yet. I'm working on the next PR that adds this functionality to the timeseries scale. There display formats will be same for both scales and then I can move it to helpers.time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
src/scales/scale.timeseries.js
Outdated
|
||
if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null && me.chart.isDatasetVisible(datasetIndex)) { | ||
// We have potential point data, so we need to parse this | ||
helpers.each(dataset.data, function(value, dataIndex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should avoid as much as possible to use function based iterations, it's a perf killer especially when iterating lot of data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replaced with vanilla js loops
Also curious how many KB this PR introduces compared to the master |
Yeah, timeseries is conceptually part time / part category However, it turns out that it's quite hard to share much code with category. I tried that first I believe, but there were only a few methods that were generally the same and even they had subtle differences that made sharing hard. I think inheriting from time is actually the better way to go as it cuts down more on the amount of code required. |
99ee03c
to
de7d098
Compare
3bfdbc4
to
5b1f038
Compare
Sizes: 155 734 bytes vs 153 051 bytes |
About a code from category scale. I'm working on the next PR that will add support of tick alignment and major units for timeseries scale. There timeseries scale have an other code to determine tick positions etc. So it was a good decision to inherit it from time scale. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @IlyaBeliaev for the updates. Just added a few more feedback that I think should be changed before merging.
There is still some pieces of code I didn't report but would be great to change for performance, minification and readability but I guess I'm too picky and don't want to keep this PR open forever.
Edit: actually, these changes mostly concern the existing code in master you refactored in
timebase
.
samples/samples.js
Outdated
@@ -105,7 +105,7 @@ | |||
path: 'scales/logarithmic/scatter.html' | |||
}] | |||
}, { | |||
title: 'Time scale', | |||
title: 'Time and TimeSeries scale', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/scales/scale.time.js
Outdated
@@ -39,7 +38,7 @@ module.exports = function(Chart) { | |||
} | |||
}; | |||
|
|||
var TimeScale = Chart.Scale.extend({ | |||
var TimeScale = Chart.TimeScaleBase.extend({ | |||
initialize: function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this initialize
override needs to be removed (looks exactly the same as the one in TimeScaleBase
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep
minUnit: 'millisecond', | ||
|
||
// defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/ | ||
displayFormats: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
src/scales/scale.timebase.js
Outdated
convertTicksToLabels: function() { | ||
var me = this; | ||
me.ticksAsTimestamps = me.ticks; | ||
me.ticks = me.ticks.map(function(tick) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to add a comment or even better, change it for a vanilla for loop and avoid doubling function calls?
getLabelCapacity: function(exampleTime) { | ||
var me = this; | ||
|
||
me.displayFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not obvious :\
@simonbrunel Thank you for the review. I think I can refactor timebase a bit in a next PR. |
}, | ||
}, | ||
ticks: { | ||
autoSkip: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IlyaBeliaev comment from @simonbrunel :
I see you turn
autoSkip
back to true for thetimeseries
? actually, that's my (hopefully) last issue: since thetime
scale doesn't supportautoSkip
, it'sfalse
by default, so can't have the same default as your PR (true
)
I wasn't sure why you needed to do this as I had it set to false
in the original code: https://github.com/chartjs/chartjs-chart-financial/blob/master/src/scale.timeseries.js#L85
Is this something you can change back to false
?
Timeseries scale added, see this issue for more info: #4189
small example here: https://codepen.io/ilyabelyaev/pen/BRvKPw