-
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
Closed
Closed
Timeseries scale #4364
Changes from 6 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
97cc62b
TimeSeries scale added; time series refactoring (#4189)
IlyaBeliaev bd6b656
Minor improvements to samples
benmccann f9121c7
minor fixes
IlyaBeliaev de7d098
docs fix; format removed from config;
IlyaBeliaev 43add34
docs and samples update
IlyaBeliaev 5b1f038
minor fixes
IlyaBeliaev 7de93d6
tick format loop refactored; samples fix; initialize method removed f…
IlyaBeliaev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
<!doctype html> | ||
<html> | ||
|
||
<head> | ||
<title>Line Chart</title> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script> | ||
<script src="../../../dist/Chart.js"></script> | ||
<script src="../../utils.js"></script> | ||
<style> | ||
canvas { | ||
-moz-user-select: none; | ||
-webkit-user-select: none; | ||
-ms-user-select: none; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<div style="width:75%;"> | ||
<canvas id="canvas"></canvas> | ||
</div> | ||
<br> | ||
<br> | ||
<button id="randomizeData">Randomize Data</button> | ||
<button id="addDataset">Add Dataset</button> | ||
<button id="removeDataset">Remove Dataset</button> | ||
<button id="addData">Add Data</button> | ||
<button id="removeData">Remove Data</button> | ||
<script> | ||
var timeFormat = 'MM/DD/YYYY HH:mm'; | ||
|
||
function newDate(days) { | ||
return moment().add(days, 'd').toDate(); | ||
} | ||
|
||
function newDateString(days) { | ||
return moment().add(days, 'd').format(); | ||
} | ||
|
||
function newTimestamp(days) { | ||
return moment().add(days, 'd').unix(); | ||
} | ||
|
||
var numDataPoints = 120; | ||
var labels = [] | ||
var data = [] | ||
for (var i = 0; i < numDataPoints; i++) { | ||
labels.push(newDate(i)); | ||
data.push(randomScalingFactor()); | ||
} | ||
|
||
var color = Chart.helpers.color; | ||
var config = { | ||
type: 'line', | ||
data: { | ||
labels: labels, | ||
datasets: [{ | ||
label: "My First dataset", | ||
backgroundColor: color(window.chartColors.red).alpha(0.5).rgbString(), | ||
borderColor: window.chartColors.red, | ||
fill: false, | ||
data: data, | ||
}] | ||
}, | ||
options: { | ||
title:{ | ||
text: "Chart.js Time Scale" | ||
}, | ||
scales: { | ||
xAxes: [{ | ||
type: "timeseries", | ||
time: { | ||
format: timeFormat, | ||
// round: 'day' | ||
tooltipFormat: 'll HH:mm' | ||
}, | ||
scaleLabel: { | ||
display: true, | ||
labelString: 'Date' | ||
} | ||
}], | ||
yAxes: [{ | ||
scaleLabel: { | ||
display: true, | ||
labelString: 'value' | ||
} | ||
}] | ||
}, | ||
} | ||
}; | ||
|
||
window.onload = function() { | ||
var ctx = document.getElementById("canvas").getContext("2d"); | ||
window.myLine = new Chart(ctx, config); | ||
|
||
}; | ||
|
||
document.getElementById('randomizeData').addEventListener('click', function() { | ||
config.data.datasets.forEach(function(dataset) { | ||
dataset.data.forEach(function(dataObj, j) { | ||
if (typeof dataObj === 'object') { | ||
dataObj.y = randomScalingFactor(); | ||
} else { | ||
dataset.data[j] = randomScalingFactor(); | ||
} | ||
}); | ||
}); | ||
|
||
window.myLine.update(); | ||
}); | ||
|
||
var colorNames = Object.keys(window.chartColors); | ||
document.getElementById('addDataset').addEventListener('click', function() { | ||
var colorName = colorNames[config.data.datasets.length % colorNames.length]; | ||
var newColor = window.chartColors[colorName] | ||
var newDataset = { | ||
label: 'Dataset ' + config.data.datasets.length, | ||
borderColor: newColor, | ||
backgroundColor: color(newColor).alpha(0.5).rgbString(), | ||
data: [], | ||
}; | ||
|
||
for (var index = 0; index < config.data.labels.length; ++index) { | ||
newDataset.data.push(randomScalingFactor()); | ||
} | ||
|
||
config.data.datasets.push(newDataset); | ||
window.myLine.update(); | ||
}); | ||
|
||
document.getElementById('addData').addEventListener('click', function() { | ||
if (config.data.datasets.length > 0) { | ||
config.data.labels.push(newDate(config.data.labels.length)); | ||
|
||
for (var index = 0; index < config.data.datasets.length; ++index) { | ||
if (typeof config.data.datasets[index].data[0] === "object") { | ||
config.data.datasets[index].data.push({ | ||
x: newDate(config.data.datasets[index].data.length), | ||
y: randomScalingFactor(), | ||
}); | ||
} else { | ||
config.data.datasets[index].data.push(randomScalingFactor()); | ||
} | ||
} | ||
|
||
window.myLine.update(); | ||
} | ||
}); | ||
|
||
document.getElementById('removeDataset').addEventListener('click', function() { | ||
config.data.datasets.splice(0, 1); | ||
window.myLine.update(); | ||
}); | ||
|
||
document.getElementById('removeData').addEventListener('click', function() { | ||
config.data.labels.splice(-1, 1); // remove the label first | ||
|
||
config.data.datasets.forEach(function(dataset, datasetIndex) { | ||
dataset.data.pop(); | ||
}); | ||
|
||
window.myLine.update(); | ||
}); | ||
</script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -219,7 +219,6 @@ module.exports = function(Chart) { | |
max: niceMax | ||
}); | ||
} | ||
|
||
}; | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,6 @@ var moment = require('moment'); | |
moment = typeof(moment) === 'function' ? moment : window.moment; | ||
|
||
module.exports = function(Chart) { | ||
|
||
var helpers = Chart.helpers; | ||
var timeHelpers = helpers.time; | ||
|
||
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more. I think this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep |
||
if (!moment) { | ||
throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com'); | ||
|
@@ -49,6 +48,7 @@ module.exports = function(Chart) { | |
|
||
Chart.Scale.prototype.initialize.call(this); | ||
}, | ||
|
||
determineDataLimits: function() { | ||
var me = this; | ||
var timeOpts = me.options.time; | ||
|
@@ -115,6 +115,7 @@ module.exports = function(Chart) { | |
me.dataMax = dataMax; | ||
me._parsedData = parsedData; | ||
}, | ||
|
||
buildTicks: function() { | ||
var me = this; | ||
var timeOpts = me.options.time; | ||
|
@@ -166,61 +167,7 @@ module.exports = function(Chart) { | |
me.max = helpers.max(me.ticks); | ||
me.min = helpers.min(me.ticks); | ||
}, | ||
// 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] : ''; | ||
var value = me.chart.data.datasets[datasetIndex].data[index]; | ||
|
||
if (value !== null && typeof value === 'object') { | ||
label = me.getRightValue(value); | ||
} | ||
|
||
// Format nicely | ||
if (me.options.time.tooltipFormat) { | ||
label = timeHelpers.parseTime(me, label).format(me.options.time.tooltipFormat); | ||
} | ||
|
||
return label; | ||
}, | ||
// Function to format an individual tick mark | ||
tickFormatFunction: function(tick, index, ticks) { | ||
var formattedTick; | ||
var tickClone = tick.clone(); | ||
var tickTimestamp = tick.valueOf(); | ||
var major = false; | ||
var tickOpts; | ||
if (this.majorUnit && this.majorDisplayFormat && tickTimestamp === tickClone.startOf(this.majorUnit).valueOf()) { | ||
// format as major unit | ||
formattedTick = tick.format(this.majorDisplayFormat); | ||
tickOpts = this.options.ticks.major; | ||
major = true; | ||
} else { | ||
// format as minor (base) unit | ||
formattedTick = tick.format(this.displayFormat); | ||
tickOpts = this.options.ticks.minor; | ||
} | ||
|
||
var callback = helpers.valueOrDefault(tickOpts.callback, tickOpts.userCallback); | ||
|
||
if (callback) { | ||
return { | ||
value: callback(formattedTick, index, ticks), | ||
major: major | ||
}; | ||
} | ||
return { | ||
value: formattedTick, | ||
major: major | ||
}; | ||
}, | ||
convertTicksToLabels: function() { | ||
var me = this; | ||
me.ticksAsTimestamps = me.ticks; | ||
me.ticks = me.ticks.map(function(tick) { | ||
return moment(tick); | ||
}).map(me.tickFormatFunction, me); | ||
}, | ||
getPixelForOffset: function(offset) { | ||
var me = this; | ||
var epochWidth = me.max - me.min; | ||
|
@@ -234,6 +181,7 @@ module.exports = function(Chart) { | |
var heightOffset = (me.height * decimal); | ||
return me.top + Math.round(heightOffset); | ||
}, | ||
|
||
getPixelForValue: function(value, index, datasetIndex) { | ||
var me = this; | ||
var offset = null; | ||
|
@@ -256,39 +204,18 @@ module.exports = function(Chart) { | |
return me.getPixelForOffset(offset); | ||
} | ||
}, | ||
|
||
getPixelForTick: function(index) { | ||
return this.getPixelForOffset(this.ticksAsTimestamps[index]); | ||
}, | ||
|
||
getValueForPixel: function(pixel) { | ||
var me = this; | ||
var innerDimension = me.isHorizontal() ? me.width : me.height; | ||
var offset = (pixel - (me.isHorizontal() ? me.left : me.top)) / innerDimension; | ||
return moment(me.min + (offset * (me.max - me.min))); | ||
}, | ||
// Crude approximation of what the label width might be | ||
getLabelWidth: function(label) { | ||
var me = this; | ||
var ticks = me.options.ticks; | ||
|
||
var tickLabelWidth = me.ctx.measureText(label).width; | ||
var cosRotation = Math.cos(helpers.toRadians(ticks.maxRotation)); | ||
var sinRotation = Math.sin(helpers.toRadians(ticks.maxRotation)); | ||
var tickFontSize = helpers.valueOrDefault(ticks.fontSize, Chart.defaults.global.defaultFontSize); | ||
return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation); | ||
}, | ||
getLabelCapacity: function(exampleTime) { | ||
var me = this; | ||
|
||
me.displayFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation | ||
var exampleLabel = me.tickFormatFunction(moment(exampleTime), 0, []).value; | ||
var tickLabelWidth = me.getLabelWidth(exampleLabel); | ||
|
||
var innerWidth = me.isHorizontal() ? me.width : me.height; | ||
var labelCapacity = innerWidth / tickLabelWidth; | ||
|
||
return labelCapacity; | ||
} | ||
}); | ||
Chart.scaleService.registerScaleType('time', TimeScale, defaultConfig); | ||
|
||
Chart.scaleService.registerScaleType('time', TimeScale, defaultConfig); | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Can we keep
title: 'Time scales'
and avoid the title on 2 lines?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