]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Add backgroundColor for scales (#8606)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Wed, 10 Mar 2021 13:18:10 +0000 (15:18 +0200)
committerGitHub <noreply@github.com>
Wed, 10 Mar 2021 13:18:10 +0000 (08:18 -0500)
* Add backgroundColor for scales
* Loosen the threshold

docs/docs/axes/_common.md
src/core/core.scale.js
src/scales/scale.radialLinear.js
test/fixtures/core.scale/backgroundColor.js [new file with mode: 0644]
test/fixtures/core.scale/backgroundColor.png [new file with mode: 0644]
test/fixtures/scale.radialLinear/backgroundColor.js [new file with mode: 0644]
test/fixtures/scale.radialLinear/backgroundColor.png [new file with mode: 0644]
test/fixtures/scale.radialLinear/circular-backgroundColor.js [new file with mode: 0644]
test/fixtures/scale.radialLinear/circular-backgroundColor.png [new file with mode: 0644]

index 9e35464611c34edbea4e1cc5669094d060f4ff76..1e9ba6450f1bc6b0e7b0e4e08f81a4e4417ef487 100644 (file)
@@ -5,6 +5,7 @@ Namespace: `options.scales[scaleId]`
 | Name | Type | Default | Description
 | ---- | ---- | ------- | -----------
 | `type` | `string` | | Type of scale being employed. Custom scales can be created and registered with a string key. This allows changing the type of an axis for a chart.
+| `backgroundColor` | [`Color`](../general/colors.md) | | Background color of the scale area.
 | `display` | `boolean`\|`string` | `true` | Controls the axis global visibility (visible when `true`, hidden when `false`). When `display: 'auto'`, the axis is visible only if at least one associated dataset is visible.
 | `gridLines` | `object` | | Grid line configuration. [more...](./styling.mdx#grid-line-configuration)
 | `min` | `number` | | User defined minimum number for the scale, overrides minimum value from data. [more...](./index.mdx#axis-range-settings)
index 684916e7fee8519be6f42a877a4db2dc6d58afc8..41606d91bcf84ab3394e9c08d4324bc1baf7d3d7 100644 (file)
@@ -1575,6 +1575,19 @@ export default class Scale extends Element {
     }
   }
 
+  /**
+   * @protected
+   */
+  drawBackground() {
+    const {ctx, options: {backgroundColor}, left, top, width, height} = this;
+    if (backgroundColor) {
+      ctx.save();
+      ctx.fillStyle = backgroundColor;
+      ctx.fillRect(left, top, width, height);
+      ctx.restore();
+    }
+  }
+
   /**
         * @protected
         */
@@ -1730,6 +1743,7 @@ export default class Scale extends Element {
       return;
     }
 
+    me.drawBackground();
     me.drawGrid(chartArea);
     me.drawTitle();
     me.drawLabels(chartArea);
@@ -1758,6 +1772,7 @@ export default class Scale extends Element {
     return [{
       z: gz,
       draw(chartArea) {
+        me.drawBackground();
         me.drawGrid(chartArea);
         me.drawTitle();
       }
index 2d04d365f9992719666ffc2969e20b2bb6e745ea..17928a7e7515254c50ce415720b35e5b487c902a 100644 (file)
@@ -93,7 +93,7 @@ function fitWithPointLabels(scale) {
   const labelSizes = [];
   const padding = [];
 
-  const valueCount = scale.chart.data.labels.length;
+  const valueCount = scale.getLabels().length;
   for (i = 0; i < valueCount; i++) {
     const opts = scale.options.pointLabels.setContext(scale.getContext(i));
     padding[i] = opts.padding;
@@ -196,17 +196,11 @@ function adjustPointPositionForLabelHeight(angle, textSize, position) {
   }
 }
 
-function drawPointLabels(scale) {
-  const ctx = scale.ctx;
-  const opts = scale.options;
-  const pointLabelOpts = opts.pointLabels;
-
-  ctx.save();
-
-  ctx.textBaseline = 'middle';
+function drawPointLabels(scale, labelCount) {
+  const {ctx, options: {pointLabels}} = scale;
 
-  for (let i = scale.chart.data.labels.length - 1; i >= 0; i--) {
-    const optsAtIndex = pointLabelOpts.setContext(scale.getContext(i));
+  for (let i = labelCount - 1; i >= 0; i--) {
+    const optsAtIndex = pointLabels.setContext(scale.getContext(i));
     const plFont = toFont(optsAtIndex.font);
     const {x, y, textAlign} = scale._pointLabelItems[i];
     renderText(
@@ -218,45 +212,47 @@ function drawPointLabels(scale) {
       {
         color: optsAtIndex.color,
         textAlign: textAlign,
+        textBaseline: 'middle'
       }
     );
   }
-  ctx.restore();
 }
 
-function drawRadiusLine(scale, gridLineOpts, radius) {
+function pathRadiusLine(scale, radius, circular, labelCount) {
+  const {ctx} = scale;
+  if (circular) {
+    // Draw circular arcs between the points
+    ctx.arc(scale.xCenter, scale.yCenter, radius, 0, TAU);
+  } else {
+    // Draw straight lines connecting each index
+    let pointPosition = scale.getPointPosition(0, radius);
+    ctx.moveTo(pointPosition.x, pointPosition.y);
+
+    for (let i = 1; i < labelCount; i++) {
+      pointPosition = scale.getPointPosition(i, radius);
+      ctx.lineTo(pointPosition.x, pointPosition.y);
+    }
+  }
+}
+
+function drawRadiusLine(scale, gridLineOpts, radius, labelCount) {
   const ctx = scale.ctx;
   const circular = gridLineOpts.circular;
-  const valueCount = scale.chart.data.labels.length;
 
-  const lineColor = gridLineOpts.color;
-  const lineWidth = gridLineOpts.lineWidth;
-  let pointPosition;
+  const {color, lineWidth} = gridLineOpts;
 
-  if ((!circular && !valueCount) || !lineColor || !lineWidth || radius < 0) {
+  if ((!circular && !labelCount) || !color || !lineWidth || radius < 0) {
     return;
   }
 
   ctx.save();
-  ctx.strokeStyle = lineColor;
+  ctx.strokeStyle = color;
   ctx.lineWidth = lineWidth;
   ctx.setLineDash(gridLineOpts.borderDash);
   ctx.lineDashOffset = gridLineOpts.borderDashOffset;
 
   ctx.beginPath();
-  if (circular) {
-    // Draw circular arcs between the points
-    ctx.arc(scale.xCenter, scale.yCenter, radius, 0, TAU);
-  } else {
-    // Draw straight lines connecting each index
-    pointPosition = scale.getPointPosition(0, radius);
-    ctx.moveTo(pointPosition.x, pointPosition.y);
-
-    for (let i = 1; i < valueCount; i++) {
-      pointPosition = scale.getPointPosition(i, radius);
-      ctx.lineTo(pointPosition.x, pointPosition.y);
-    }
-  }
+  pathRadiusLine(scale, radius, circular, labelCount);
   ctx.closePath();
   ctx.stroke();
   ctx.restore();
@@ -319,7 +315,7 @@ export default class RadialLinearScale extends LinearScaleBase {
     LinearScaleBase.prototype.generateTickLabels.call(me, ticks);
 
     // Point labels
-    me._pointLabels = me.chart.data.labels.map((value, index) => {
+    me._pointLabels = me.getLabels().map((value, index) => {
       const label = callCallback(me.options.pointLabels.callback, [value, index], me);
       return label || label === 0 ? label : '';
     });
@@ -428,6 +424,24 @@ export default class RadialLinearScale extends LinearScaleBase {
     };
   }
 
+  /**
+        * @protected
+        */
+  drawBackground() {
+    const me = this;
+    const {backgroundColor, gridLines: {circular}} = me.options;
+    if (backgroundColor) {
+      const ctx = me.ctx;
+      ctx.save();
+      ctx.beginPath();
+      pathRadiusLine(me, me.getDistanceFromCenterForValue(me._endValue), circular, me.getLabels().length);
+      ctx.closePath();
+      ctx.fillStyle = backgroundColor;
+      ctx.fill();
+      ctx.restore();
+    }
+  }
+
   /**
         * @protected
         */
@@ -435,31 +449,31 @@ export default class RadialLinearScale extends LinearScaleBase {
     const me = this;
     const ctx = me.ctx;
     const opts = me.options;
-    const gridLineOpts = opts.gridLines;
-    const angleLineOpts = opts.angleLines;
+    const {angleLines, gridLines} = opts;
+    const labelCount = me.getLabels().length;
+
     let i, offset, position;
 
     if (opts.pointLabels.display) {
-      drawPointLabels(me);
+      drawPointLabels(me, labelCount);
     }
 
-    if (gridLineOpts.display) {
+    if (gridLines.display) {
       me.ticks.forEach((tick, index) => {
         if (index !== 0) {
-          offset = me.getDistanceFromCenterForValue(me.ticks[index].value);
-          const optsAtIndex = gridLineOpts.setContext(me.getContext(index - 1));
-          drawRadiusLine(me, optsAtIndex, offset);
+          offset = me.getDistanceFromCenterForValue(tick.value);
+          const optsAtIndex = gridLines.setContext(me.getContext(index - 1));
+          drawRadiusLine(me, optsAtIndex, offset, labelCount);
         }
       });
     }
 
-    if (angleLineOpts.display) {
+    if (angleLines.display) {
       ctx.save();
 
-      for (i = me.chart.data.labels.length - 1; i >= 0; i--) {
-        const optsAtIndex = angleLineOpts.setContext(me.getContext(i));
-        const lineWidth = optsAtIndex.lineWidth;
-        const color = optsAtIndex.color;
+      for (i = me.getLabels().length - 1; i >= 0; i--) {
+        const optsAtIndex = angleLines.setContext(me.getContext(i));
+        const {color, lineWidth} = optsAtIndex;
 
         if (!lineWidth || !color) {
           continue;
@@ -518,11 +532,12 @@ export default class RadialLinearScale extends LinearScaleBase {
         width = ctx.measureText(tick.label).width;
         ctx.fillStyle = optsAtIndex.backdropColor;
 
+        const {backdropPaddingX, backdropPaddingY} = optsAtIndex;
         ctx.fillRect(
-          -width / 2 - optsAtIndex.backdropPaddingX,
-          -offset - tickFont.size / 2 - optsAtIndex.backdropPaddingY,
-          width + optsAtIndex.backdropPaddingX * 2,
-          tickFont.size + optsAtIndex.backdropPaddingY * 2
+          -width / 2 - backdropPaddingX,
+          -offset - tickFont.size / 2 - backdropPaddingY,
+          width + backdropPaddingX * 2,
+          tickFont.size + backdropPaddingY * 2
         );
       }
 
diff --git a/test/fixtures/core.scale/backgroundColor.js b/test/fixtures/core.scale/backgroundColor.js
new file mode 100644 (file)
index 0000000..47be546
--- /dev/null
@@ -0,0 +1,58 @@
+const ticks = {
+  display: false
+};
+const gridLines = {
+  display: false
+};
+const title = {
+  display: true,
+  test: ''
+};
+module.exports = {
+  config: {
+    type: 'line',
+    options: {
+      events: [],
+      scales: {
+        top: {
+          type: 'linear',
+          backgroundColor: 'red',
+          position: 'top',
+          ticks,
+          gridLines,
+          title
+        },
+        left: {
+          type: 'linear',
+          backgroundColor: 'green',
+          position: 'left',
+          ticks,
+          gridLines,
+          title
+        },
+        bottom: {
+          type: 'linear',
+          backgroundColor: 'blue',
+          position: 'bottom',
+          ticks,
+          gridLines,
+          title
+        },
+        right: {
+          type: 'linear',
+          backgroundColor: 'gray',
+          position: 'right',
+          ticks,
+          gridLines,
+          title
+        },
+      }
+    }
+  },
+  options: {
+    canvas: {
+      height: 256,
+      width: 256
+    },
+  }
+};
diff --git a/test/fixtures/core.scale/backgroundColor.png b/test/fixtures/core.scale/backgroundColor.png
new file mode 100644 (file)
index 0000000..5855420
Binary files /dev/null and b/test/fixtures/core.scale/backgroundColor.png differ
diff --git a/test/fixtures/scale.radialLinear/backgroundColor.js b/test/fixtures/scale.radialLinear/backgroundColor.js
new file mode 100644 (file)
index 0000000..405877d
--- /dev/null
@@ -0,0 +1,37 @@
+module.exports = {
+  threshold: 0.01,
+  config: {
+    type: 'radar',
+    data: {
+      labels: [1, 2, 3, 4, 5, 6],
+      datasets: [
+        {
+          data: [3, 2, 2, 1, 3, 1]
+        }
+      ]
+    },
+    options: {
+      plugins: {
+        legend: false,
+        tooltip: false,
+        filler: false
+      },
+      scales: {
+        r: {
+          backgroundColor: '#00FF00',
+          min: 0,
+          max: 3,
+          pointLabels: {
+            display: false
+          },
+          ticks: {
+            display: false,
+            stepSize: 1,
+          }
+        }
+      },
+      responsive: true,
+      maintainAspectRatio: false
+    }
+  },
+};
diff --git a/test/fixtures/scale.radialLinear/backgroundColor.png b/test/fixtures/scale.radialLinear/backgroundColor.png
new file mode 100644 (file)
index 0000000..d61a1c9
Binary files /dev/null and b/test/fixtures/scale.radialLinear/backgroundColor.png differ
diff --git a/test/fixtures/scale.radialLinear/circular-backgroundColor.js b/test/fixtures/scale.radialLinear/circular-backgroundColor.js
new file mode 100644 (file)
index 0000000..5e21f24
--- /dev/null
@@ -0,0 +1,40 @@
+module.exports = {
+  threshold: 0.05,
+  config: {
+    type: 'radar',
+    data: {
+      labels: [1, 2, 3, 4, 5, 6],
+      datasets: [
+        {
+          data: [3, 2, 2, 1, 3, 1]
+        }
+      ]
+    },
+    options: {
+      plugins: {
+        legend: false,
+        tooltip: false,
+        filler: false
+      },
+      scales: {
+        r: {
+          backgroundColor: '#00FF00',
+          min: 0,
+          max: 3,
+          gridLines: {
+            circular: true
+          },
+          pointLabels: {
+            display: false
+          },
+          ticks: {
+            display: false,
+            stepSize: 1,
+          }
+        }
+      },
+      responsive: true,
+      maintainAspectRatio: false
+    }
+  },
+};
diff --git a/test/fixtures/scale.radialLinear/circular-backgroundColor.png b/test/fixtures/scale.radialLinear/circular-backgroundColor.png
new file mode 100644 (file)
index 0000000..5da9a2d
Binary files /dev/null and b/test/fixtures/scale.radialLinear/circular-backgroundColor.png differ