Skip to content

Commit 5e23a42

Browse files
committed
Remove ticksToTimestamps and change ticks to numbers
1 parent 090b5ae commit 5e23a42

18 files changed

+134
-161
lines changed

docs/getting-started/v3-migration.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,9 @@ Chart.js 3.0 introduces a number of breaking changes. Chart.js 2.0 was released
124124
##### Ticks
125125

126126
* When the `autoSkip` option is enabled, `Scale.ticks` now contains only the non-skipped ticks instead of all ticks.
127-
* `Scale.ticks` now contains objects instead of strings
128-
* `Scale.buildTicks` is now expected to return tick objects
127+
* `Scale.ticks` now contains the tick values instead of labels, which are now available in `Scale.labels`
129128
* `Scale.afterBuildTicks` now has no parameters like the other callbacks
130-
* `Scale.convertTicksToLabels` was renamed to `generateTickLabels`. It is now expected to set the label property on the ticks given as input
129+
* `TimeScale.buildTicks` is now expected to return `number`s like the other scales
131130

132131
##### Time Scale
133132

src/core/core.helpers.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,6 @@ module.exports = function() {
8282
}
8383
}
8484
};
85-
helpers._setMinAndMaxByKey = function(array, target, property) {
86-
var i, ilen, value;
87-
88-
for (i = 0, ilen = array.length; i < ilen; i++) {
89-
value = array[i][property];
90-
if (!isNaN(value)) {
91-
target.min = Math.min(target.min, value);
92-
target.max = Math.max(target.max, value);
93-
}
94-
}
95-
};
9685
helpers.sign = Math.sign ?
9786
function(x) {
9887
return Math.sign(x);

src/core/core.scale.js

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,17 @@ function garbageCollect(caches, length) {
123123
* Returns {width, height, offset} objects for the first, last, widest, highest tick
124124
* labels where offset indicates the anchor point offset from the top in pixels.
125125
*/
126-
function computeLabelSizes(ctx, tickFonts, ticks, caches) {
127-
var length = ticks.length;
126+
function computeLabelSizes(ctx, tickFonts, labels, tickMeta, caches) {
127+
var length = labels.length;
128128
var widths = [];
129129
var heights = [];
130130
var offsets = [];
131-
var i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel, widest, highest;
131+
var i, j, jlen, label, meta, tickFont, fontString, cache, lineHeight, width, height, nestedLabel, widest, highest;
132132

133133
for (i = 0; i < length; ++i) {
134-
label = ticks[i].label;
135-
tickFont = ticks[i].major ? tickFonts.major : tickFonts.minor;
134+
label = labels[i];
135+
meta = tickMeta[i];
136+
tickFont = meta && meta.major ? tickFonts.major : tickFonts.minor;
136137
ctx.font = fontString = tickFont.string;
137138
cache = caches[fontString] = caches[fontString] || {data: {}, gc: []};
138139
lineHeight = tickFont.lineHeight;
@@ -249,18 +250,18 @@ function calculateSpacing(majorIndices, ticks, axisLength, ticksLimit) {
249250
return Math.max(spacing, 1);
250251
}
251252

252-
function getMajorIndices(ticks) {
253+
function getMajorIndices(meta) {
253254
var result = [];
254255
var i, ilen;
255-
for (i = 0, ilen = ticks.length; i < ilen; i++) {
256-
if (ticks[i].major) {
256+
for (i = 0, ilen = meta.length; i < ilen; i++) {
257+
if (meta[i] && meta[i].major) {
257258
result.push(i);
258259
}
259260
}
260261
return result;
261262
}
262263

263-
function skipMajors(ticks, newTicks, majorIndices, spacing) {
264+
function skipMajors(ticks, meta, newTicks, newMeta, majorIndices, spacing) {
264265
let count = 0;
265266
let next = majorIndices[0];
266267
let i;
@@ -269,13 +270,14 @@ function skipMajors(ticks, newTicks, majorIndices, spacing) {
269270
for (i = 0; i < ticks.length; i++) {
270271
if (i === next) {
271272
newTicks.push(ticks[i]);
273+
newMeta.push(meta[i]);
272274
count++;
273275
next = majorIndices[count * spacing];
274276
}
275277
}
276278
}
277279

278-
function skip(ticks, newTicks, spacing, majorStart, majorEnd) {
280+
function skip(ticks, meta, newTicks, newMeta, spacing, majorStart, majorEnd) {
279281
const start = valueOrDefault(majorStart, 0);
280282
const end = Math.min(valueOrDefault(majorEnd, ticks.length), ticks.length);
281283
let count = 0;
@@ -297,6 +299,7 @@ function skip(ticks, newTicks, spacing, majorStart, majorEnd) {
297299
for (i = Math.max(start, 0); i < end; i++) {
298300
if (i === next) {
299301
newTicks.push(ticks[i]);
302+
newMeta.push(meta[i]);
300303
count++;
301304
next = Math.round(start + count * spacing);
302305
}
@@ -427,10 +430,10 @@ class Scale extends Element {
427430
* - thickness of scales or legends in another orientation
428431
*/
429432
update(maxWidth, maxHeight, margins) {
430-
var me = this;
431-
var tickOpts = me.options.ticks;
432-
var sampleSize = tickOpts.sampleSize;
433-
var samplingEnabled;
433+
const me = this;
434+
const tickOpts = me.options.ticks;
435+
const sampleSize = tickOpts.sampleSize;
436+
const autoSkipEnabled = tickOpts.autoSkip || tickOpts.source === 'auto';
434437

435438
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
436439
me.beforeUpdate();
@@ -446,6 +449,7 @@ class Scale extends Element {
446449
}, margins);
447450

448451
me.ticks = null;
452+
me._tickMeta = [];
449453
me._labelSizes = null;
450454
me._maxLabelLines = 0;
451455
me.longestLabelWidth = 0;
@@ -472,8 +476,8 @@ class Scale extends Element {
472476

473477
// Compute tick rotation and fit using a sampled subset of labels
474478
// We generally don't need to compute the size of every single label for determining scale size
475-
samplingEnabled = sampleSize < me.ticks.length;
476-
me._convertTicksToLabels(samplingEnabled ? sample(me.ticks, sampleSize) : me.ticks);
479+
const samplingEnabled = sampleSize < me.ticks.length;
480+
me.labels = me._convertTicksToLabels(samplingEnabled ? sample(me.ticks, sampleSize) : me.ticks);
477481

478482
// _configure is called twice, once here, once from core.controller.updateLayout.
479483
// Here we haven't been positioned yet, but dimensions are correct.
@@ -491,11 +495,13 @@ class Scale extends Element {
491495
me.afterFit();
492496

493497
// Auto-skip
494-
me.ticks = tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto') ? me._autoSkip(me.ticks) : me.ticks;
498+
if (tickOpts.display && autoSkipEnabled) {
499+
me._autoSkip();
500+
}
495501

496-
if (samplingEnabled) {
502+
if (tickOpts.display && (samplingEnabled || autoSkipEnabled)) {
497503
// Generate labels using all non-skipped ticks
498-
me._convertTicksToLabels(me.ticks);
504+
me.labels = me._convertTicksToLabels(me.ticks);
499505
}
500506

501507
// IMPORTANT: after this point, we consider that `this.ticks` will NEVER change!
@@ -589,14 +595,15 @@ class Scale extends Element {
589595
/**
590596
* Convert ticks to label strings
591597
*/
592-
generateTickLabels(ticks) {
598+
convertTicksToLabels(ticks) {
593599
var me = this;
594600
var tickOpts = me.options.ticks;
595-
var i, ilen, tick;
601+
var labels = [];
602+
var i, ilen;
596603
for (i = 0, ilen = ticks.length; i < ilen; i++) {
597-
tick = ticks[i];
598-
tick.label = helpers.callback(tickOpts.callback, [tick.value, i, ticks], me);
604+
labels[i] = helpers.callback(tickOpts.callback, [ticks[i], i, ticks], me);
599605
}
606+
return labels;
600607
}
601608
afterTickToLabelConversion() {
602609
helpers.callback(this.options.afterTickToLabelConversion, [this]);
@@ -787,12 +794,15 @@ class Scale extends Element {
787794

788795
_convertTicksToLabels(ticks) {
789796
var me = this;
797+
var labels;
790798

791799
me.beforeTickToLabelConversion();
792800

793-
me.generateTickLabels(ticks);
801+
labels = me.convertTicksToLabels(ticks);
794802

795803
me.afterTickToLabelConversion();
804+
805+
return labels;
796806
}
797807

798808
/**
@@ -803,7 +813,7 @@ class Scale extends Element {
803813
var labelSizes = me._labelSizes;
804814

805815
if (!labelSizes) {
806-
me._labelSizes = labelSizes = computeLabelSizes(me.ctx, parseTickFontOptions(me.options.ticks), me.ticks, me.longestTextCache);
816+
me._labelSizes = labelSizes = computeLabelSizes(me.ctx, parseTickFontOptions(me.options.ticks), me.labels, me._tickMeta, me.longestTextCache);
807817
me.longestLabelWidth = labelSizes.widest.width;
808818
}
809819

@@ -891,37 +901,46 @@ class Scale extends Element {
891901
* Returns a subset of ticks to be plotted to avoid overlapping labels.
892902
* @private
893903
*/
894-
_autoSkip(ticks) {
904+
_autoSkip() {
895905
const me = this;
896906
const tickOpts = me.options.ticks;
907+
const ticks = me.ticks;
908+
const meta = me._tickMeta;
897909
const axisLength = me._length;
898910
const ticksLimit = tickOpts.maxTicksLimit || axisLength / me._tickSize() + 1;
899-
const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];
911+
const majorIndices = tickOpts.major.enabled ? getMajorIndices(meta) : [];
900912
const numMajorIndices = majorIndices.length;
901913
const first = majorIndices[0];
902914
const last = majorIndices[numMajorIndices - 1];
903915
const newTicks = [];
916+
const newMeta = [];
904917

905918
// If there are too many major ticks to display them all
906919
if (numMajorIndices > ticksLimit) {
907-
skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);
908-
return newTicks;
920+
skipMajors(ticks, meta, newTicks, newMeta, majorIndices, numMajorIndices / ticksLimit);
921+
me._tickMeta = newMeta;
922+
me.ticks = newTicks;
923+
return;
909924
}
910925

911926
const spacing = calculateSpacing(majorIndices, ticks, axisLength, ticksLimit);
912927

913928
if (numMajorIndices > 0) {
914929
let i, ilen;
915930
const avgMajorSpacing = numMajorIndices > 1 ? (last - first) / (numMajorIndices - 1) : null;
916-
skip(ticks, newTicks, spacing, helpers.isNullOrUndef(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);
931+
skip(ticks, meta, newTicks, newMeta, spacing, helpers.isNullOrUndef(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);
917932
for (i = 0, ilen = numMajorIndices - 1; i < ilen; i++) {
918-
skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]);
933+
skip(ticks, meta, newTicks, newMeta, spacing, majorIndices[i], majorIndices[i + 1]);
919934
}
920-
skip(ticks, newTicks, spacing, last, helpers.isNullOrUndef(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);
921-
return newTicks;
935+
skip(ticks, meta, newTicks, newMeta, spacing, last, helpers.isNullOrUndef(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);
936+
me._tickMeta = newMeta;
937+
me.ticks = newTicks;
938+
return;
922939
}
923-
skip(ticks, newTicks, spacing);
924-
return newTicks;
940+
skip(ticks, meta, newTicks, newMeta, spacing);
941+
me._tickMeta = newMeta;
942+
me.ticks = newTicks;
943+
return;
925944
}
926945

927946
/**
@@ -943,8 +962,8 @@ class Scale extends Element {
943962

944963
// Calculate space needed for 1 tick in axis direction.
945964
return me.isHorizontal()
946-
? h * cos > w * sin ? w / cos : h / sin
947-
: h * sin < w * cos ? h / cos : w / sin;
965+
? (h * cos > w * sin ? w / cos : h / sin)
966+
: (h * sin < w * cos ? h / cos : w / sin);
948967
}
949968

950969
/**
@@ -1080,7 +1099,7 @@ class Scale extends Element {
10801099
var tl = getTickMarkLength(options.gridLines);
10811100
var rotation = -helpers.toRadians(me.labelRotation);
10821101
var items = [];
1083-
var i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;
1102+
var i, ilen, meta, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;
10841103

10851104
if (position === 'top') {
10861105
y = me.bottom - tl - tickPadding;
@@ -1097,11 +1116,11 @@ class Scale extends Element {
10971116
}
10981117

10991118
for (i = 0, ilen = ticks.length; i < ilen; ++i) {
1100-
tick = ticks[i];
1101-
label = tick.label;
1119+
meta = me._tickMeta[i];
1120+
label = me.labels[i];
11021121

11031122
pixel = me.getPixelForTick(i) + optionTicks.labelOffset;
1104-
font = tick.major ? fonts.major : fonts.minor;
1123+
font = meta && meta.major ? fonts.major : fonts.minor;
11051124
lineHeight = font.lineHeight;
11061125
lineCount = isArray(label) ? label.length : 1;
11071126

src/core/core.ticks.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ module.exports = {
3333
*/
3434
linear: function(tickValue, index, ticks) {
3535
// If we have lots of ticks, don't use the ones
36-
var delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;
36+
var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
3737

3838
// If we have a number like 2.5 as the delta, figure out how many decimal places we need
3939
if (Math.abs(delta) > 1) {
@@ -47,7 +47,7 @@ module.exports = {
4747
var tickString = '';
4848

4949
if (tickValue !== 0) {
50-
var maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
50+
var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1]));
5151
if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation
5252
var logTick = math.log10(Math.abs(tickValue));
5353
var numExponential = Math.floor(logTick) - Math.floor(logDelta);

src/scales/scale.category.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class CategroyScale extends Scale {
3131
// If we are viewing some subset of labels, slice the original array
3232
labels = (min === 0 && max === labels.length - 1) ? labels : labels.slice(min, max + 1);
3333
return labels.map(function(l) {
34-
return {value: l};
34+
return l;
3535
});
3636
}
3737

src/scales/scale.linear.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class LinearScale extends LinearScaleBase {
6464
}
6565

6666
getPixelForTick(index) {
67-
var ticks = this._tickValues;
67+
var ticks = this.ticks;
6868
if (index < 0 || index > ticks.length - 1) {
6969
return null;
7070
}

src/scales/scale.linearbase.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function generateTicks(generationOptions, dataRange) {
3232
// Beyond MIN_SPACING floating point numbers being to lose precision
3333
// such that we can't do the math necessary to generate ticks
3434
if (spacing < MIN_SPACING && isNullOrUndef(min) && isNullOrUndef(max)) {
35-
return [{value: rmin}, {value: rmax}];
35+
return [rmin, rmax];
3636
}
3737

3838
numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);
@@ -74,11 +74,11 @@ function generateTicks(generationOptions, dataRange) {
7474

7575
niceMin = Math.round(niceMin * factor) / factor;
7676
niceMax = Math.round(niceMax * factor) / factor;
77-
ticks.push({value: isNullOrUndef(min) ? niceMin : min});
77+
ticks.push(isNullOrUndef(min) ? niceMin : min);
7878
for (var j = 1; j < numSpaces; ++j) {
79-
ticks.push({value: Math.round((niceMin + j * spacing) * factor) / factor});
79+
ticks.push(Math.round((niceMin + j * spacing) * factor) / factor);
8080
}
81-
ticks.push({value: isNullOrUndef(max) ? niceMax : max});
81+
ticks.push(isNullOrUndef(max) ? niceMax : max);
8282

8383
return ticks;
8484
}
@@ -215,7 +215,7 @@ class LinearScaleBase extends Scale {
215215

216216
// At this point, we need to update our max and min given the tick values since we have expanded the
217217
// range of the scale
218-
helpers._setMinAndMaxByKey(ticks, me, 'value');
218+
helpers._setMinAndMax(ticks, me);
219219

220220
if (opts.reverse) {
221221
ticks.reverse();
@@ -230,12 +230,6 @@ class LinearScaleBase extends Scale {
230230
return ticks;
231231
}
232232

233-
generateTickLabels(ticks) {
234-
var me = this;
235-
me._tickValues = ticks.map(t => t.value);
236-
Scale.prototype.generateTickLabels.call(me, ticks);
237-
}
238-
239233
_configure() {
240234
var me = this;
241235
var ticks = me.getTicks();

0 commit comments

Comments
 (0)