From 1f6d0a244bdc1636cb42dce1ce1cc22f2caa0a51 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Mon, 15 Mar 2021 08:49:25 -0400 Subject: [PATCH] Linear Scale: Ability to specify a fixed number of ticks (#8643) * Option to specify exact number of ticks on linear scale * Fix issue description in tests * Add tests for conditions where min/max do not align with niceMin/niceMax * Refactor linear tick generation algorithm * Add TS definitions * Update docs * Code review feedback + lint fixes --- docs/docs/axes/cartesian/linear.mdx | 1 + docs/docs/axes/radial/linear.mdx | 1 + src/scales/scale.linearbase.js | 78 ++++++++++++------ .../scale.linear/tick-count-data-limits.js | 28 +++++++ .../scale.linear/tick-count-data-limits.png | Bin 0 -> 27020 bytes .../tick-count-min-max-not-aligned.js | 23 ++++++ .../tick-count-min-max-not-aligned.png | Bin 0 -> 11023 bytes .../scale.linear/tick-count-min-max.js | 23 ++++++ .../scale.linear/tick-count-min-max.png | Bin 0 -> 18369 bytes .../scale.linear/tick-step-min-max.js | 23 ++++++ .../scale.linear/tick-step-min-max.png | Bin 0 -> 11023 bytes types/index.esm.d.ts | 10 +++ 12 files changed, 161 insertions(+), 26 deletions(-) create mode 100644 test/fixtures/scale.linear/tick-count-data-limits.js create mode 100644 test/fixtures/scale.linear/tick-count-data-limits.png create mode 100644 test/fixtures/scale.linear/tick-count-min-max-not-aligned.js create mode 100644 test/fixtures/scale.linear/tick-count-min-max-not-aligned.png create mode 100644 test/fixtures/scale.linear/tick-count-min-max.js create mode 100644 test/fixtures/scale.linear/tick-count-min-max.png create mode 100644 test/fixtures/scale.linear/tick-step-min-max.js create mode 100644 test/fixtures/scale.linear/tick-step-min-max.png diff --git a/docs/docs/axes/cartesian/linear.mdx b/docs/docs/axes/cartesian/linear.mdx index bd6670297..5a5f8588a 100644 --- a/docs/docs/axes/cartesian/linear.mdx +++ b/docs/docs/axes/cartesian/linear.mdx @@ -31,6 +31,7 @@ Namespace: `options.scales[scaleId].ticks` | Name | Type | Default | Description | ---- | ---- | ------- | ----------- +| `count` | `number` | `undefined` | The number of ticks to generate. If specified, this overrides the automatic generation. | `format` | `object` | | The [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) options used by the default label formatter | `maxTicksLimit` | `number` | `11` | Maximum number of ticks and gridlines to show. | `precision` | `number` | | if defined and `stepSize` is not specified, the step size will be rounded to this many decimal places. diff --git a/docs/docs/axes/radial/linear.mdx b/docs/docs/axes/radial/linear.mdx index e66f8a414..663e949b4 100644 --- a/docs/docs/axes/radial/linear.mdx +++ b/docs/docs/axes/radial/linear.mdx @@ -35,6 +35,7 @@ Namespace: `options.scales[scaleId].ticks` | ---- | ---- | ------- | ------- | ----------- | `backdropColor` | [`Color`](../../general/colors.md) | Yes | `'rgba(255, 255, 255, 0.75)'` | Color of label backdrops. | `backdropPadding` | [`Padding`](../../general/padding.md) | Yes | `2` | Padding of label backdrop. +| `count` | `number` | Yes | `undefined` | The number of ticks to generate. If specified, this overrides the automatic generation. | `format` | `object` | Yes | | The [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) options used by the default label formatter | `maxTicksLimit` | `number` | Yes | `11` | Maximum number of ticks and gridlines to show. | `precision` | `number` | Yes | | if defined and `stepSize` is not specified, the step size will be rounded to this many decimal places. diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index 1dbaf285a..be5b0508c 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -5,7 +5,20 @@ import {formatNumber} from '../core/core.intl'; import {_addGrace} from '../helpers/helpers.options'; /** - * Generate a set of linear ticks + * Generate a set of linear ticks for an axis + * 1. If generationOptions.min, generationOptions.max, and generationOptions.step are defined: + * if (max - min) / step is an integer, ticks are generated as [min, min + step, ..., max] + * Note that the generationOptions.maxCount setting is respected in this scenario + * + * 2. If generationOptions.min, generationOptions.max, and generationOptions.count is defined + * spacing = (max - min) / count + * Ticks are generated as [min, min + spacing, ..., max] + * + * 3. If generationOptions.count is defined + * spacing = (niceMax - niceMin) / count + * + * 4. Compute optimal spacing of ticks using niceNum algorithm + * * @param generationOptions the options used to generate the ticks * @param dataRange the range of the data * @returns {object[]} array of tick objects @@ -17,13 +30,14 @@ function generateTicks(generationOptions, dataRange) { // for details. const MIN_SPACING = 1e-14; - const {stepSize, min, max, precision} = generationOptions; - const unit = stepSize || 1; - const maxNumSpaces = generationOptions.maxTicks - 1; + const {step, min, max, precision, count, maxTicks} = generationOptions; + const unit = step || 1; + const maxSpaces = maxTicks - 1; const {min: rmin, max: rmax} = dataRange; const minDefined = !isNullOrUndef(min); const maxDefined = !isNullOrUndef(max); - let spacing = niceNum((rmax - rmin) / maxNumSpaces / unit) * unit; + const countDefined = !isNullOrUndef(count); + let spacing = niceNum((rmax - rmin) / maxSpaces / unit) * unit; let factor, niceMin, niceMax, numSpaces; // Beyond MIN_SPACING floating point numbers being to lose precision @@ -33,15 +47,12 @@ function generateTicks(generationOptions, dataRange) { } numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing); - if (numSpaces > maxNumSpaces) { + if (numSpaces > maxSpaces) { // If the calculated num of spaces exceeds maxNumSpaces, recalculate it - spacing = niceNum(numSpaces * spacing / maxNumSpaces / unit) * unit; + spacing = niceNum(numSpaces * spacing / maxSpaces / unit) * unit; } - if (stepSize || isNullOrUndef(precision)) { - // If a precision is not specified, calculate factor based on spacing - factor = Math.pow(10, _decimalPlaces(spacing)); - } else { + if (!isNullOrUndef(precision)) { // If the user specified a precision, round to that number of decimal places factor = Math.pow(10, precision); spacing = Math.ceil(spacing * factor) / factor; @@ -50,23 +61,37 @@ function generateTicks(generationOptions, dataRange) { niceMin = Math.floor(rmin / spacing) * spacing; niceMax = Math.ceil(rmax / spacing) * spacing; - // If min, max and stepSize is set and they make an evenly spaced scale use it. - if (stepSize && minDefined && maxDefined) { - // If very close to our whole number, use it. - if (almostWhole((max - min) / stepSize, spacing / 1000)) { - niceMin = min; - niceMax = max; - } - } - - numSpaces = (niceMax - niceMin) / spacing; - // If very close to our rounded value, use it. - if (almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) { - numSpaces = Math.round(numSpaces); + if (minDefined && maxDefined && step && almostWhole((max - min) / step, spacing / 1000)) { + // Case 1: If min, max and stepSize are set and they make an evenly spaced scale use it. + // spacing = step; + // numSpaces = (max - min) / spacing; + numSpaces = Math.min((max - min) / spacing, maxTicks); + spacing = (max - min) / numSpaces; + niceMin = min; + niceMax = max; + } else if (countDefined) { + // Cases 2 & 3, we have a count specified. Handle optional user defined edges to the range. + // Sometimes these are no-ops, but it makes the code a lot clearer + // and when a user defined range is specified, we want the correct ticks + niceMin = minDefined ? min : niceMin; + niceMax = maxDefined ? max : niceMax; + numSpaces = count - 1; + spacing = (niceMax - niceMin) / numSpaces; } else { - numSpaces = Math.ceil(numSpaces); + // Case 4 + numSpaces = (niceMax - niceMin) / spacing; + + // If very close to our rounded value, use it. + if (almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) { + numSpaces = Math.round(numSpaces); + } else { + numSpaces = Math.ceil(numSpaces); + } } + // The spacing will have changed in cases 1, 2, and 3 so the factor cannot be computed + // until this point + factor = Math.pow(10, isNullOrUndef(precision) ? _decimalPlaces(spacing) : precision); niceMin = Math.round(niceMin * factor) / factor; niceMax = Math.round(niceMax * factor) / factor; @@ -204,7 +229,8 @@ export default class LinearScaleBase extends Scale { min: opts.min, max: opts.max, precision: tickOpts.precision, - stepSize: tickOpts.stepSize + step: tickOpts.stepSize, + count: tickOpts.count, }; const ticks = generateTicks(numericGeneratorOptions, _addGrace(me, opts.grace)); diff --git a/test/fixtures/scale.linear/tick-count-data-limits.js b/test/fixtures/scale.linear/tick-count-data-limits.js new file mode 100644 index 000000000..497ed1145 --- /dev/null +++ b/test/fixtures/scale.linear/tick-count-data-limits.js @@ -0,0 +1,28 @@ +module.exports = { + description: 'https://github.com/chartjs/Chart.js/issues/4234', + config: { + type: 'line', + data: { + datasets: [{ + data: [0, 2, 45, 30] + }], + labels: ['A', 'B', 'C', 'D'] + }, + options: { + scales: { + y: { + ticks: { + count: 21, + callback: (v) => v.toString(), + } + }, + x: { + display: false + } + } + } + }, + options: { + spriteText: true + } +}; diff --git a/test/fixtures/scale.linear/tick-count-data-limits.png b/test/fixtures/scale.linear/tick-count-data-limits.png new file mode 100644 index 0000000000000000000000000000000000000000..bb365bcd1f150ed78c51b883884e3627031be641 GIT binary patch literal 27020 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 F{{wVR=%fGu literal 0 Hc-jL100001 diff --git a/test/fixtures/scale.linear/tick-count-min-max.js b/test/fixtures/scale.linear/tick-count-min-max.js new file mode 100644 index 000000000..49ec3fba8 --- /dev/null +++ b/test/fixtures/scale.linear/tick-count-min-max.js @@ -0,0 +1,23 @@ +module.exports = { + description: 'https://github.com/chartjs/Chart.js/issues/4234', + config: { + type: 'line', + options: { + scales: { + y: { + max: 50, + min: 0, + ticks: { + count: 21, + } + }, + x: { + display: false + } + } + } + }, + options: { + spriteText: true + } +}; diff --git a/test/fixtures/scale.linear/tick-count-min-max.png b/test/fixtures/scale.linear/tick-count-min-max.png new file mode 100644 index 0000000000000000000000000000000000000000..dcba5ad841f3c09c4ed6f38f2a8e31c314c9c222 GIT binary patch literal 18369 zc-qx`2T)Ymw)W{Jg9wU>hzJHiKtKdUK%k8XB1o2uN>DN)IW=ZQKt&`7g5)5el7oOc z1eG9JG75rZB&Y8F*XeHN&fNFzt5@&+_pkb=oSJI8&p!L?z1J7kT4(N`S660b-ocC@ z2&>AOlUfLZMbLj4>ESf!iT7wJf`DeI?=-tt={^B^gCN_+4A$Q{mkjDcP4d#Uj#-ua$3H zB^iz_#(HuMNHomW`bAhT412ySeeiCv)An7v*Sm#91MdmKU?>Z3wR5!jgHPe&W@YBV z1KVlYaR`Q%y(SVb!fB4h)yoAWY$E?nVJ|j|7C$&>F&w6E`blT8De0{3hg(c?&OdG` zE)Q~4R#%T@l}u_~zn&|slWM+bN#F0~E;D=ry%g6^qBUkhn3$N|Om; z@=_fY?^i{Z8vKa^YcpTOg|(9(=G%3|mlGx&z2;l>Tg&}P<5-+Z!yXM^CTO*d5`=l7Hr@$F~m?ckSnAuc1imx$k#*)BOl5o#p=i zRigNm7hb9{^6q+SY7fh85k|z*ZK?4fx|0Fi{4kg8hb->RPWh9JZZfdtXAtV<$_;3~ z#-CzgaUIcv35%=khOw~XFcTc&Q}nN3*y@LgWY6UwMo zgdt9&Ekc6){HM~=(u7S*3w;M-iz=Qs+-Bh%7sXGNlT7KDw|tEy&IxjFsI6{DK?>=d z5>7J=pCTW|9CR1hN!t(%U&BVF9e2=ebxNRRL}XN7%FL{WH4ajAL@>6l zrYUvg`M==gLp=N#5%RD4PhqflPVbn*Cq5>DcdW zTcymc{{@1nP&li4oIE<89ZdXUv#!n-%Don8-?Ab~YtuKq=6=285LCbN`$y$MZIWu( zXRVtIygmmnum0p#BCWY7td8eIE@;(wq|Z=uuo-rqLL2 zbxL1L>xt-U$y8YmNx^+Gy6u%g0+FyPA|P;jqN||c+N6f!@=5WsrTCTku@pJi(QgyW zv%~rj2#iR;^{szS866j5ttCZ+_gsve?&HUgxiEZ$IUymT9a2{w)xS{4C@ehE<29CP zU~|~{$4S;*M=#6{H?*H%Q+Rq+9#ioyIB_2ZOR$@!xsdv3*#W!0vL5xZ=Z;JI^oUEN zS-xGQ*WzU6#gBJJ#Qm4Q=r(j^=!*yODw(!s=!Y|H8JdE_l)t(e!Hx(okdFbbLID$t z>4#YbFAtF_XxLKWS_3S8dBM?&0Sz&@aBQK=vD_vzJ|Q8`;?w532#JrqVi89@-<}TM znP$_Pz6t3bQ(oT(J{Zj$PHS+{uw&V>5+G3|7H4P}b=dA(97Op@Qn;yB!wUu1=5sP8 z^M5D@?`({ew7xzZ<31WFUUnYfV6(@OCGK1x?i$CN8mK`?F@8N&mZHKaj>AT5SMnNOs&Ef zeNcE5cjhho&1rBpHt7yUKex5MGHA|XI^r=McV{DyaLxz+k*1{L;TPU(>5)u`Zn}o=G)WtvtO97yuMV)yt>p2r(&W6Q@iK= z{8)R2)AtWt(vqv~nMV2}4J*%2-LM+<|NKC>llowO&!rD~6t#t98EHke-?5i4>R=I=wGD^>s~RifO-2>Z96By4mj%xJCJ= zn<+drt<2Yj^lR*XKY0RS)C(S1=PSSlYrmaAIlwGUtop zID~OkED=M&U0N~t*!^%XWdufV3>NpzeK#wPayp#gW53nT0Lp;hSlE#dWh_?_%18n5 z5i2vmNIBsj00h_2+wgXj~ksaxF zPTWErL=~>m>p5jfc}yqeidN*c`;=*(ZM%APFpo9_b>{bC*D)PH2DQAPhYxeRis<^) z1+}OT7r3-V)NK-y=?iJNw^WJ(c>mnWPSqO8^685F`-=B^6L${O6i ze}A;6#61}?KmPuY`yBH%dqb`)PWGUeG+90F?R zD<5ptEpX^LfH7a5`Dysp;yx=QVP(Gg+ndX}De63ED4DoyJV^jLfe zOXd&A*G!`<;_a&*NLg2Q4E`9NvX2aOjL5F>>roFWrxSyh_+NYh=rzZ?#FWGY45n)G znF4DS1@N23fc4)1VR4EXgI2pccqDkwo?0W%B*6Z$rQZW`o->Jl^BHC%0ABj`ZO=IoZ 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 literal 0 Hc-jL100001 diff --git a/test/fixtures/scale.linear/tick-step-min-max.js b/test/fixtures/scale.linear/tick-step-min-max.js new file mode 100644 index 000000000..115549b91 --- /dev/null +++ b/test/fixtures/scale.linear/tick-step-min-max.js @@ -0,0 +1,23 @@ +module.exports = { + description: 'https://github.com/chartjs/Chart.js/issues/4234', + config: { + type: 'line', + options: { + scales: { + y: { + max: 27, + min: -3, + ticks: { + stepSize: 3, + } + }, + x: { + display: false + } + } + } + }, + options: { + spriteText: true + } +}; diff --git a/test/fixtures/scale.linear/tick-step-min-max.png b/test/fixtures/scale.linear/tick-step-min-max.png new file mode 100644 index 0000000000000000000000000000000000000000..dea42ece524ee5fedfa0a124e4a75e532e11d3b7 GIT binary patch literal 11023 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 F{{wVR=%fGu literal 0 Hc-jL100001 diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index d12b52500..936c9f938 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -2825,6 +2825,11 @@ export type LinearScaleOptions = CartesianScaleOptions & { * @see https://www.chartjs.org/docs/next/axes/cartesian/linear#step-size */ stepSize: number; + + /** + * User defined count of ticks + */ + count: number; }; }; @@ -3080,6 +3085,11 @@ export type RadialLinearScaleOptions = CoreScaleOptions & { */ stepSize: number; + /** + * User defined number of ticks + */ + count: number; + /** * If true, draw a background behind the tick labels. * @default true -- 2.47.3