]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Add 'shape' mode for filler-plugin (#9360)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Mon, 5 Jul 2021 21:03:19 +0000 (00:03 +0300)
committerGitHub <noreply@github.com>
Mon, 5 Jul 2021 21:03:19 +0000 (17:03 -0400)
docs/charts/area.md
src/plugins/plugin.filler.js
test/fixtures/plugin.filler/line/shape.js [new file with mode: 0644]
test/fixtures/plugin.filler/line/shape.png [new file with mode: 0644]
types/index.esm.d.ts

index 39e7f22218a51bc7ef4b9180fb8e5700f907e4f3..5dc8a50498051c7c5e8a72aaaa414148b01f224d 100644 (file)
@@ -16,6 +16,7 @@ This feature is implemented by the [`filler` plugin](https://github.com/chartjs/
 | Disabled <sup>1</sup> | `boolean` | `false` |
 | Stacked value below | `string` | `'stack'` |
 | Axis value | `object` | `{ value: number; }` |
+| Shape (fill inside line) | `string` | `'shape'` |
 
 > <sup>1</sup> for backward compatibility, `fill: true` is equivalent to `fill: 'origin'`<br/>
 
index 4b70e2cf41f586c33026ac9e47da1c46c5d472ff..9e3e3b8f5769b5a1f4c9a11466cb890e132bb366 100644 (file)
@@ -74,7 +74,7 @@ function decodeFill(line, index, count) {
     return target;
   }
 
-  return ['origin', 'start', 'end', 'stack'].indexOf(fill) >= 0 && fill;
+  return ['origin', 'start', 'end', 'stack', 'shape'].indexOf(fill) >= 0 && fill;
 }
 
 function computeLinearBoundary(source) {
@@ -315,6 +315,10 @@ function getTarget(source) {
     return buildStackLine(source);
   }
 
+  if (fill === 'shape') {
+    return true;
+  }
+
   const boundary = computeBoundary(source);
 
   if (boundary instanceof simpleArc) {
@@ -481,24 +485,30 @@ function _fill(ctx, cfg) {
 
   for (const {source: src, target: tgt, start, end} of segments) {
     const {style: {backgroundColor = color} = {}} = src;
+    const notShape = target !== true;
+
     ctx.save();
     ctx.fillStyle = backgroundColor;
 
-    clipBounds(ctx, scale, getBounds(property, start, end));
+    clipBounds(ctx, scale, notShape && getBounds(property, start, end));
 
     ctx.beginPath();
 
     const lineLoop = !!line.pathSegment(ctx, src);
-    if (lineLoop) {
-      ctx.closePath();
-    } else {
-      interpolatedLineTo(ctx, target, end, property);
-    }
 
-    const targetLoop = !!target.pathSegment(ctx, tgt, {move: lineLoop, reverse: true});
-    const loop = lineLoop && targetLoop;
-    if (!loop) {
-      interpolatedLineTo(ctx, target, start, property);
+    let loop;
+    if (notShape) {
+      if (lineLoop) {
+        ctx.closePath();
+      } else {
+        interpolatedLineTo(ctx, target, end, property);
+      }
+
+      const targetLoop = !!target.pathSegment(ctx, tgt, {move: lineLoop, reverse: true});
+      loop = lineLoop && targetLoop;
+      if (!loop) {
+        interpolatedLineTo(ctx, target, start, property);
+      }
     }
 
     ctx.closePath();
diff --git a/test/fixtures/plugin.filler/line/shape.js b/test/fixtures/plugin.filler/line/shape.js
new file mode 100644 (file)
index 0000000..3a78bc7
--- /dev/null
@@ -0,0 +1,35 @@
+const data = [];
+for (let rad = 0; rad <= Math.PI * 2; rad += Math.PI / 45) {
+  data.push({
+    x: Math.cos(rad),
+    y: Math.sin(rad)
+  });
+}
+
+module.exports = {
+  config: {
+    type: 'line',
+    data: {
+      datasets: [{
+        data,
+        fill: 'shape',
+        backgroundColor: 'rgba(255, 0, 0, 0.5)',
+      }]
+    },
+    options: {
+      plugins: {
+        legend: false
+      },
+      scales: {
+        x: {
+          type: 'linear',
+          display: false
+        },
+        y: {
+          type: 'linear',
+          display: false
+        },
+      },
+    }
+  }
+};
diff --git a/test/fixtures/plugin.filler/line/shape.png b/test/fixtures/plugin.filler/line/shape.png
new file mode 100644 (file)
index 0000000..08e5998
Binary files /dev/null and b/test/fixtures/plugin.filler/line/shape.png differ
index 1598bc8288e2e70b50a240ad799a57a4703bee22..d26a63396950847d840466a4b0bec6171c1c7201 100644 (file)
@@ -2011,7 +2011,7 @@ export interface FillerOptions {
   propagate: boolean;
 }
 
-export type FillTarget = number | string | { value: number } | 'start' | 'end' | 'origin' | 'stack' | boolean;
+export type FillTarget = number | string | { value: number } | 'start' | 'end' | 'origin' | 'stack' | 'shape' | boolean;
 
 export interface ComplexFillTarget {
   /**