]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Improve linear tick generators collision estimation (#8983)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Wed, 28 Apr 2021 20:41:57 +0000 (23:41 +0300)
committerGitHub <noreply@github.com>
Wed, 28 Apr 2021 20:41:57 +0000 (16:41 -0400)
* Increase distance to min/max tick to 1/3 space

* Better estimation on linear tick collision

* Lint fix

* Remove unused change

src/core/core.scale.js
src/scales/scale.linearbase.js
test/fixtures/scale.linear/min-max-skip-edge-case-1.js [new file with mode: 0644]
test/fixtures/scale.linear/min-max-skip-edge-case-1.png [new file with mode: 0644]
test/fixtures/scale.linear/min-max-skip-edge-case-2.js [new file with mode: 0644]
test/fixtures/scale.linear/min-max-skip-edge-case-2.png [new file with mode: 0644]
test/fixtures/scale.linear/min-max-skip-edge-case-3.js [new file with mode: 0644]
test/fixtures/scale.linear/min-max-skip-edge-case-3.png [new file with mode: 0644]
test/fixtures/scale.linear/min-max-skip-edge-case-4.js [new file with mode: 0644]
test/fixtures/scale.linear/min-max-skip-edge-case-4.png [new file with mode: 0644]

index 5b793a6f38244f647ef4e36b5b2c38ffb9219d29..f5feb9fff77297b00c910efd7ee6d5f394772e3f 100644 (file)
@@ -1658,4 +1658,13 @@ export default class Scale extends Element {
     const opts = this.options.ticks.setContext(this.getContext(index));
     return toFont(opts.font);
   }
+
+  /**
+   * @protected
+   */
+  _maxDigits() {
+    const me = this;
+    const fontSize = me._resolveTickFontOptions(0).lineHeight;
+    return me.isHorizontal() ? me.width / fontSize / 0.7 : me.height / fontSize;
+  }
 }
index 9eda15c33d3e3b8d677935b24a3db0f1b8be18cd..de1dbe967e57415283673dc2c04aef6e6e8cc7a6 100644 (file)
@@ -29,13 +29,14 @@ function generateTicks(generationOptions, dataRange) {
   // for details.
 
   const MIN_SPACING = 1e-14;
-  const {step, min, max, precision, count, maxTicks} = generationOptions;
+  const {step, min, max, precision, count, maxTicks, maxDigits, horizontal} = generationOptions;
   const unit = step || 1;
   const maxSpaces = maxTicks - 1;
   const {min: rmin, max: rmax} = dataRange;
   const minDefined = !isNullOrUndef(min);
   const maxDefined = !isNullOrUndef(max);
   const countDefined = !isNullOrUndef(count);
+  const minSpacing = (rmax - rmin) / maxDigits;
   let spacing = niceNum((rmax - rmin) / maxSpaces / unit) * unit;
   let factor, niceMin, niceMax, numSpaces;
 
@@ -102,7 +103,7 @@ function generateTicks(generationOptions, dataRange) {
       j++;
     }
     // If the next nice tick is close to min, skip that too
-    if (almostEquals(Math.round((niceMin + j * spacing) * factor) / factor, min, spacing / 10)) {
+    if (almostEquals(Math.round((niceMin + j * spacing) * factor) / factor, min, minSpacing * (horizontal ? ('' + min).length : 1))) {
       j++;
     }
   }
@@ -113,7 +114,7 @@ function generateTicks(generationOptions, dataRange) {
 
   if (maxDefined) {
     // If the previous tick is close to max, replace it with max, else add max
-    if (almostEquals(ticks[ticks.length - 1].value, max, spacing / 10)) {
+    if (almostEquals(ticks[ticks.length - 1].value, max, minSpacing * (horizontal ? ('' + max).length : 1))) {
       ticks[ticks.length - 1].value = max;
     } else {
       ticks.push({value: max});
@@ -230,6 +231,8 @@ export default class LinearScaleBase extends Scale {
       precision: tickOpts.precision,
       step: tickOpts.stepSize,
       count: tickOpts.count,
+      maxDigits: me._maxDigits(),
+      horizontal: me.isHorizontal()
     };
     const dataRange = me._range || me;
     const ticks = generateTicks(numericGeneratorOptions, dataRange);
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-1.js b/test/fixtures/scale.linear/min-max-skip-edge-case-1.js
new file mode 100644 (file)
index 0000000..89a6dd8
--- /dev/null
@@ -0,0 +1,31 @@
+module.exports = {
+  description: 'https://github.com/chartjs/Chart.js/issues/8982',
+  config: {
+    type: 'scatter',
+    options: {
+      scales: {
+        y: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        },
+        x: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        }
+      }
+    }
+  },
+  options: {
+    spriteText: true,
+    canvas: {
+      height: 211,
+      width: 408
+    }
+  }
+};
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-1.png b/test/fixtures/scale.linear/min-max-skip-edge-case-1.png
new file mode 100644 (file)
index 0000000..9401c0e
Binary files /dev/null and b/test/fixtures/scale.linear/min-max-skip-edge-case-1.png differ
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-2.js b/test/fixtures/scale.linear/min-max-skip-edge-case-2.js
new file mode 100644 (file)
index 0000000..8325a4d
--- /dev/null
@@ -0,0 +1,31 @@
+module.exports = {
+  description: 'https://github.com/chartjs/Chart.js/issues/8982',
+  config: {
+    type: 'scatter',
+    options: {
+      scales: {
+        y: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        },
+        x: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        }
+      }
+    }
+  },
+  options: {
+    spriteText: true,
+    canvas: {
+      height: 212,
+      width: 409
+    }
+  }
+};
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-2.png b/test/fixtures/scale.linear/min-max-skip-edge-case-2.png
new file mode 100644 (file)
index 0000000..f2f878f
Binary files /dev/null and b/test/fixtures/scale.linear/min-max-skip-edge-case-2.png differ
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-3.js b/test/fixtures/scale.linear/min-max-skip-edge-case-3.js
new file mode 100644 (file)
index 0000000..eca5a11
--- /dev/null
@@ -0,0 +1,31 @@
+module.exports = {
+  description: 'https://github.com/chartjs/Chart.js/issues/8982',
+  config: {
+    type: 'scatter',
+    options: {
+      scales: {
+        y: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        },
+        x: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        }
+      }
+    }
+  },
+  options: {
+    spriteText: true,
+    canvas: {
+      height: 213,
+      width: 536
+    }
+  }
+};
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-3.png b/test/fixtures/scale.linear/min-max-skip-edge-case-3.png
new file mode 100644 (file)
index 0000000..55cc3cb
Binary files /dev/null and b/test/fixtures/scale.linear/min-max-skip-edge-case-3.png differ
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-4.js b/test/fixtures/scale.linear/min-max-skip-edge-case-4.js
new file mode 100644 (file)
index 0000000..3993e37
--- /dev/null
@@ -0,0 +1,31 @@
+module.exports = {
+  description: 'https://github.com/chartjs/Chart.js/issues/8982',
+  config: {
+    type: 'scatter',
+    options: {
+      scales: {
+        y: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        },
+        x: {
+          max: 1069,
+          min: 230,
+          ticks: {
+            autoSkip: false
+          }
+        }
+      }
+    }
+  },
+  options: {
+    spriteText: true,
+    canvas: {
+      height: 214,
+      width: 537
+    }
+  }
+};
diff --git a/test/fixtures/scale.linear/min-max-skip-edge-case-4.png b/test/fixtures/scale.linear/min-max-skip-edge-case-4.png
new file mode 100644 (file)
index 0000000..2f7f627
Binary files /dev/null and b/test/fixtures/scale.linear/min-max-skip-edge-case-4.png differ