]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Legend boxes support borderRadius (#8875)
authorEvert Timberg <evert.timberg+github@gmail.com>
Sat, 10 Apr 2021 19:05:34 +0000 (15:05 -0400)
committerGitHub <noreply@github.com>
Sat, 10 Apr 2021 19:05:34 +0000 (15:05 -0400)
docs/configuration/legend.md
src/plugins/plugin.legend.js
test/fixtures/plugin.legend/borderRadius/legend-border-radius.js [new file with mode: 0644]
test/fixtures/plugin.legend/borderRadius/legend-border-radius.png [new file with mode: 0644]
test/specs/plugin.legend.tests.js
types/index.esm.d.ts

index e1ff2cbf86903f63aae11c665dd3753874b134dd..0be48c975b544e18842530d3ecb9859638ae8dff 100644 (file)
@@ -84,6 +84,10 @@ Items passed to the legend `onClick` function are the ones returned from `labels
     // Label that will be displayed
     text: string,
 
+    // Border radius of the legend item.
+    // Introduced in 3.1.0
+    borderRadius?: number | BorderRadius,
+
     // Index of the associated dataset
     datasetIndex: number,
 
index e1d3c65c1d624e0924efbed9f0fe747ca39dd8e0..b30ba41d30135468e90e9d904bf61bb96bf39388 100644 (file)
@@ -1,13 +1,14 @@
 import defaults from '../core/core.defaults';
 import Element from '../core/core.element';
 import layouts from '../core/core.layouts';
-import {drawPoint, renderText} from '../helpers/helpers.canvas';
+import {addRoundedRectPath, drawPoint, renderText} from '../helpers/helpers.canvas';
 import {
   callback as call, valueOrDefault, toFont,
   toPadding, getRtlAdapter, overrideTextDirection, restoreTextDirection,
   clipArea, unclipArea
 } from '../helpers/index';
 import {_toLeftRightCenter, _alignStartEnd, _textX} from '../helpers/helpers.extras';
+import {toTRBLCorners} from '../helpers/helpers.options';
 /**
  * @typedef { import("../platform/platform.base").ChartEvent } ChartEvent
  */
@@ -341,10 +342,26 @@ export class Legend extends Element {
         // Draw box as legend symbol
         // Adjust position when boxHeight < fontSize (want it centered)
         const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0);
+        const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth);
+        const borderRadius = toTRBLCorners(legendItem.borderRadius);
+
+        ctx.beginPath();
+
+        if (Object.values(borderRadius).some(v => v !== 0)) {
+          addRoundedRectPath(ctx, {
+            x: xBoxLeft,
+            y: yBoxTop,
+            w: boxWidth,
+            h: boxHeight,
+            radius: borderRadius,
+          });
+        } else {
+          ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight);
+        }
 
-        ctx.fillRect(rtlHelper.leftForLtr(x, boxWidth), yBoxTop, boxWidth, boxHeight);
+        ctx.fill();
         if (lineWidth !== 0) {
-          ctx.strokeRect(rtlHelper.leftForLtr(x, boxWidth), yBoxTop, boxWidth, boxHeight);
+          ctx.stroke();
         }
       }
 
@@ -653,6 +670,7 @@ export default {
             pointStyle: pointStyle || style.pointStyle,
             rotation: style.rotation,
             textAlign: textAlign || style.textAlign,
+            borderRadius: 0, // TODO: v4, default to style.borderRadius
 
             // Below is extra data used for toggling the datasets
             datasetIndex: meta.index
diff --git a/test/fixtures/plugin.legend/borderRadius/legend-border-radius.js b/test/fixtures/plugin.legend/borderRadius/legend-border-radius.js
new file mode 100644 (file)
index 0000000..d765134
--- /dev/null
@@ -0,0 +1,55 @@
+module.exports = {
+  config: {
+    type: 'line',
+    data: {
+      labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
+      datasets: [
+        {
+          label: '# of Votes',
+          data: [12, 19, 3, 5, 2, 3],
+          borderWidth: 1,
+          borderColor: '#FF0000',
+          backgroundColor: '#00FF00',
+        },
+        {
+          label: '# of Points',
+          data: [7, 11, 5, 8, 3, 7],
+          borderWidth: 2,
+          borderColor: '#FF00FF',
+          backgroundColor: '#0000FF',
+        }
+      ]
+    },
+    options: {
+      scales: {
+        x: {display: false},
+        y: {display: false}
+      },
+      plugins: {
+        title: false,
+        tooltip: false,
+        filler: false,
+        legend: {
+          labels: {
+            generateLabels: (chart) => {
+              const items = Chart.defaults.plugins.legend.labels.generateLabels(chart);
+
+              for (const item of items) {
+                item.borderRadius = 5;
+              }
+
+              return items;
+            }
+          }
+        }
+      }
+    }
+  },
+  options: {
+    spriteText: true,
+    canvas: {
+      width: 512,
+      height: 256
+    }
+  }
+};
diff --git a/test/fixtures/plugin.legend/borderRadius/legend-border-radius.png b/test/fixtures/plugin.legend/borderRadius/legend-border-radius.png
new file mode 100644 (file)
index 0000000..600c3db
Binary files /dev/null and b/test/fixtures/plugin.legend/borderRadius/legend-border-radius.png differ
index 701b07a82a034f7ea7083cb618bf0661bcb6336f..2006dabe0f13e400b319787da3796c7dfaa8af43 100644 (file)
@@ -61,6 +61,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
@@ -76,6 +77,7 @@ describe('Legend block tests', function() {
       datasetIndex: 0
     }, {
       text: 'dataset2',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: true,
@@ -91,6 +93,7 @@ describe('Legend block tests', function() {
       datasetIndex: 1
     }, {
       text: 'dataset3',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: false,
@@ -137,6 +140,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
@@ -152,6 +156,7 @@ describe('Legend block tests', function() {
       datasetIndex: 0
     }, {
       text: 'dataset2',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: true,
@@ -167,6 +172,7 @@ describe('Legend block tests', function() {
       datasetIndex: 1
     }, {
       text: 'dataset3',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: false,
@@ -220,6 +226,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset3',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: false,
@@ -235,6 +242,7 @@ describe('Legend block tests', function() {
       datasetIndex: 2
     }, {
       text: 'dataset2',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: true,
@@ -250,6 +258,7 @@ describe('Legend block tests', function() {
       datasetIndex: 1
     }, {
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
@@ -308,6 +317,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
@@ -323,6 +333,7 @@ describe('Legend block tests', function() {
       datasetIndex: 0
     }, {
       text: 'dataset3',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: false,
@@ -380,6 +391,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset3',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: false,
@@ -395,6 +407,7 @@ describe('Legend block tests', function() {
       datasetIndex: 2
     }, {
       text: 'dataset2',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: true,
@@ -410,6 +423,7 @@ describe('Legend block tests', function() {
       datasetIndex: 1
     }, {
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
@@ -542,6 +556,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
@@ -585,6 +600,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: 'rgb(50, 0, 0)',
       fontColor: '#666',
       hidden: false,
@@ -643,6 +659,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: false,
@@ -658,6 +675,7 @@ describe('Legend block tests', function() {
       datasetIndex: 0
     }, {
       text: 'dataset2',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
@@ -717,6 +735,7 @@ describe('Legend block tests', function() {
 
     expect(chart.legend.legendItems).toEqual([{
       text: 'dataset1',
+      borderRadius: 0,
       fillStyle: 'rgba(0,0,0,0.1)',
       fontColor: '#666',
       hidden: false,
@@ -732,6 +751,7 @@ describe('Legend block tests', function() {
       datasetIndex: 0
     }, {
       text: 'dataset2',
+      borderRadius: 0,
       fillStyle: '#f31',
       fontColor: '#666',
       hidden: false,
index 71f01be031b18a10e3985d0adbfb34def6718f7a..a0535beb3dae9d4e41a1fffc73e1bdfdb337906a 100644 (file)
@@ -2009,6 +2009,12 @@ export interface LegendItem {
    */
   text: string;
 
+  /**
+   * Border radius of the legend box
+   * @since 3.1.0
+   */
+  borderRadius?: number | BorderRadius;
+
   /**
    * Index of the associated dataset
    */