var ticks = [];
if (options.maxTicks) {
var stepSize = options.stepSize;
- ticks.push(options.min !== undefined ? options.min : niceRange.min);
- var cur = moment(niceRange.min);
- while (cur.add(stepSize, options.unit).valueOf() < niceRange.max) {
- ticks.push(cur.valueOf());
+ var startTick = options.min !== undefined ? options.min : niceRange.min;
+ var majorUnit = options.majorUnit;
+ var majorUnitStart = majorUnit ? moment(startTick).add(1, majorUnit).startOf(majorUnit) : startTick;
+ var startRange = majorUnitStart.valueOf() - startTick;
+ var stepValue = interval[options.unit].size * stepSize;
+ var startFraction = startRange % stepValue;
+ var alignedTick = startTick;
+ if (startFraction && majorUnit && !options.timeOpts.round && !options.timeOpts.isoWeekday) {
+ alignedTick += startFraction - stepValue;
+ ticks.push(alignedTick);
+ } else {
+ ticks.push(startTick);
}
+ var cur = moment(alignedTick);
var realMax = options.max || niceRange.max;
- if (ticks[ticks.length - 1] !== realMax) {
- ticks.push(realMax);
+ while (cur.add(stepSize, options.unit).valueOf() < realMax) {
+ ticks.push(cur.valueOf());
}
+ ticks.push(cur.valueOf());
}
return ticks;
}
return unit;
},
+ /**
+ * Determine major unit accordingly to passed unit
+ * @param unit {String} relative unit
+ * @return {String} major unit
+ */
+ determineMajorUnit: function(unit) {
+ var units = Object.keys(interval);
+ var majorUnit = null;
+ var unitIndex = units.indexOf(unit);
+ if (unitIndex < units.length - 1) {
+ majorUnit = units[unitIndex + 1];
+ }
+
+ return majorUnit;
+ },
+
/**
* Determines how we scale the unit
* @param min {Number} the scale minimum
generateTicks: function(options, dataRange) {
var niceMin;
var niceMax;
- var isoWeekday = options.isoWeekday;
+ var isoWeekday = options.timeOpts.isoWeekday;
if (options.unit === 'week' && isoWeekday !== false) {
niceMin = moment(dataRange.min).startOf('isoWeek').isoWeekday(isoWeekday).valueOf();
niceMax = moment(dataRange.max).startOf('isoWeek').isoWeekday(isoWeekday);
labels: ['2015-01-01T12:00:00', '2015-01-02T21:00:00', '2015-01-03T22:00:00', '2015-01-05T23:00:00', '2015-01-07T03:00', '2015-01-08T10:00', '2015-01-10T12:00'], // days
};
- var scale = createScale(mockData, Chart.scaleService.getScaleDefaults('time'));
+ var scaleOptions = Chart.scaleService.getScaleDefaults('time');
+ var scale = createScale(mockData, scaleOptions);
scale.update(1000, 200);
expect(scale.ticks).toEqual(['Jan 1, 2015', 'Jan 2, 2015', 'Jan 3, 2015', 'Jan 4, 2015', 'Jan 5, 2015', 'Jan 6, 2015', 'Jan 7, 2015', 'Jan 8, 2015', 'Jan 9, 2015', 'Jan 10, 2015', 'Jan 11, 2015']);
});
var scale = createScale(mockData, config);
scale.update(2500, 200);
+
expect(scale.ticks).toEqual(['Jan 1, 8PM', 'Jan 1, 9PM', 'Jan 1, 10PM', 'Jan 1, 11PM', 'Jan 2, 12AM', 'Jan 2, 1AM', 'Jan 2, 2AM', 'Jan 2, 3AM', 'Jan 2, 4AM', 'Jan 2, 5AM', 'Jan 2, 6AM', 'Jan 2, 7AM', 'Jan 2, 8AM', 'Jan 2, 9AM', 'Jan 2, 10AM', 'Jan 2, 11AM', 'Jan 2, 12PM', 'Jan 2, 1PM', 'Jan 2, 2PM', 'Jan 2, 3PM', 'Jan 2, 4PM', 'Jan 2, 5PM', 'Jan 2, 6PM', 'Jan 2, 7PM', 'Jan 2, 8PM', 'Jan 2, 9PM']);
});
config.time.max = '2015-01-05T06:00:00';
var scale = createScale(mockData, config);
- expect(scale.ticks[scale.ticks.length - 1]).toEqual('Jan 5, 2015');
+ expect(scale.ticks[scale.ticks.length - 1]).toEqual('Jan 6, 2015');
});
});
var xScale = chart.scales.xScale0;
- it('should be bounded by the nearest day beginnings', function() {
- expect(xScale.getValueForPixel(xScale.left)).toBeCloseToTime({
- value: moment(chart.data.labels[0]).startOf('day'),
- unit: 'hour',
- });
- expect(xScale.getValueForPixel(xScale.right)).toBeCloseToTime({
- value: moment(chart.data.labels[chart.data.labels.length - 1]).endOf('day'),
- unit: 'hour',
- });
+ it('should be bounded by the nearest week beginnings', function() {
+ expect(xScale.getValueForPixel(xScale.left)).toBeGreaterThan(moment(chart.data.labels[0]).startOf('week'));
+ expect(xScale.getValueForPixel(xScale.right)).toBeLessThan(moment(chart.data.labels[chart.data.labels.length - 1]).add(1, 'week').endOf('week'));
});
it('should convert between screen coordinates and times', function() {
- var timeRange = moment('2015-01-11').valueOf() - moment('2015-01-01').valueOf();
- var msInHour = 3600000;
- var firstLabelAlong = 20 * msInHour / timeRange;
- var firstLabelPixel = xScale.left + (xScale.width * firstLabelAlong);
- var lastLabelAlong = (timeRange - (12 * msInHour)) / timeRange;
- var lastLabelPixel = xScale.left + (xScale.width * lastLabelAlong);
-
- expect(xScale.getPixelForValue('', 0, 0)).toBeCloseToPixel(firstLabelPixel);
- expect(xScale.getPixelForValue(chart.data.labels[0])).toBeCloseToPixel(firstLabelPixel);
- expect(xScale.getValueForPixel(firstLabelPixel)).toBeCloseToTime({
+ var timeRange = moment(xScale.max).valueOf() - moment(xScale.min).valueOf();
+ var msPerPix = timeRange / xScale.width;
+ var firstPointOffsetMs = moment(chart.config.data.labels[0]).valueOf() - xScale.min;
+ var firstPointPixel = xScale.left + firstPointOffsetMs / msPerPix;
+ var lastPointOffsetMs = moment(chart.config.data.labels[chart.config.data.labels.length - 1]).valueOf() - xScale.min;
+ var lastPointPixel = xScale.left + lastPointOffsetMs / msPerPix;
+
+ expect(xScale.getPixelForValue('', 0, 0)).toBeCloseToPixel(firstPointPixel);
+ expect(xScale.getPixelForValue(chart.data.labels[0])).toBeCloseToPixel(firstPointPixel);
+ expect(xScale.getValueForPixel(firstPointPixel)).toBeCloseToTime({
value: moment(chart.data.labels[0]),
unit: 'hour',
});
- expect(xScale.getPixelForValue('', 6, 0)).toBeCloseToPixel(lastLabelPixel);
- expect(xScale.getValueForPixel(lastLabelPixel)).toBeCloseToTime({
+ expect(xScale.getPixelForValue('', 6, 0)).toBeCloseToPixel(lastPointPixel);
+ expect(xScale.getValueForPixel(lastPointPixel)).toBeCloseToTime({
value: moment(chart.data.labels[6]),
unit: 'hour'
});
var xScale = chart.scales.xScale0;
xScale.update(800, 200);
+ var step = xScale.ticksAsTimestamps[1] - xScale.ticksAsTimestamps[0];
+ var stepsAmount = Math.floor((xScale.max - xScale.min) / step);
- it('should be bounded by nearest year starts', function() {
+ it('should be bounded by nearest step year starts', function() {
expect(xScale.getValueForPixel(xScale.left)).toBeCloseToTime({
- value: moment(chart.data.labels[0]).startOf('year'),
+ value: moment(xScale.min).startOf('year'),
unit: 'hour',
});
expect(xScale.getValueForPixel(xScale.right)).toBeCloseToTime({
- value: moment(chart.data.labels[chart.data.labels - 1]).endOf('year'),
+ value: moment(xScale.min + step * stepsAmount).endOf('year'),
unit: 'hour',
});
});
it('should build the correct ticks', function() {
- // Where 'correct' is a two year spacing, except the last tick which is the year end of the last point.
- expect(xScale.ticks).toEqual(['2005', '2007', '2009', '2011', '2013', '2015', '2017', '2018']);
+ // Where 'correct' is a two year spacing.
+ expect(xScale.ticks).toEqual(['2005', '2007', '2009', '2011', '2013', '2015', '2017', '2019']);
});
it('should have ticks with accurate labels', function() {
var ticks = xScale.ticks;
- var pixelsPerYear = xScale.width / 13;
+ var pixelsPerYear = xScale.width / 14;
for (var i = 0; i < ticks.length - 1; i++) {
var offset = 2 * pixelsPerYear * i;
});
var xScale = chart.scales.xScale0;
+ var pixel = xScale.getPixelForValue('', 0, 0);
- expect(xScale.getPixelForValue('', 0, 0)).toBeCloseToPixel(62);
-
- expect(xScale.getValueForPixel(62)).toBeCloseToTime({
- value: moment(chart.data.labels[0]),
- unit: 'day',
- });
+ expect(xScale.getValueForPixel(pixel).valueOf()).toEqual(moment(chart.data.labels[0]).valueOf());
});
it('does not create a negative width chart when hidden', function() {