From ee7e928cfe821e2a283a05afa47f0ac2c8b83d40 Mon Sep 17 00:00:00 2001 From: stockiNail Date: Fri, 28 Apr 2023 00:25:13 +0200 Subject: [PATCH] Enable applying of gradients and pattern on line segments (#11217) * Enable applying of gradients and pattern on line segments * add test case * improve replacer --- src/helpers/helpers.segment.js | 16 ++++++++- .../controller.line/segments/gradient.js | 34 ++++++++++++++++++ .../controller.line/segments/gradient.png | Bin 0 -> 16971 bytes 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/controller.line/segments/gradient.js create mode 100644 test/fixtures/controller.line/segments/gradient.png diff --git a/src/helpers/helpers.segment.js b/src/helpers/helpers.segment.js index 0c6dbfd0c..50ea8da5b 100644 --- a/src/helpers/helpers.segment.js +++ b/src/helpers/helpers.segment.js @@ -1,5 +1,6 @@ import {_angleBetween, _angleDiff, _isBetween, _normalizeAngle} from './helpers.math.js'; import {createContext} from './helpers.options.js'; +import {isPatternOrGradient} from './helpers.color.js'; /** * @typedef { import('../elements/element.line.js').default } LineElement @@ -346,5 +347,18 @@ function readStyle(options) { } function styleChanged(style, prevStyle) { - return prevStyle && JSON.stringify(style) !== JSON.stringify(prevStyle); + if (!prevStyle) { + return false; + } + const cache = []; + const replacer = function(key, value) { + if (!isPatternOrGradient(value)) { + return value; + } + if (!cache.includes(value)) { + cache.push(value); + } + return cache.indexOf(value); + }; + return JSON.stringify(style, replacer) !== JSON.stringify(prevStyle, replacer); } diff --git a/test/fixtures/controller.line/segments/gradient.js b/test/fixtures/controller.line/segments/gradient.js new file mode 100644 index 000000000..8a09503e9 --- /dev/null +++ b/test/fixtures/controller.line/segments/gradient.js @@ -0,0 +1,34 @@ +const getGradient = (context) => { + const {chart, p0, p1} = context; + const ctx = chart.ctx; + const {x: x0} = p0.getProps(['x'], true); + const {x: x1} = p1.getProps(['x'], true); + const gradient = ctx.createLinearGradient(x0, 0, x1, 0); + gradient.addColorStop(0, p0.options.backgroundColor); + gradient.addColorStop(1, p1.options.backgroundColor); + return gradient; +}; + +module.exports = { + config: { + type: 'line', + data: { + datasets: [{ + data: [{x: 0, y: 0}, {x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 3}, {x: 4, y: 4}, {x: 5, y: 5}, {x: 6, y: 6}], + pointBackgroundColor: ['red', 'yellow', 'green', 'green', 'blue', 'pink', 'blue'], + pointBorderWidth: 0, + pointRadius: 10, + borderWidth: 5, + segment: { + borderColor: getGradient, + } + }] + }, + options: { + scales: { + x: {type: 'linear', display: false}, + y: {display: false} + } + } + } +}; diff --git a/test/fixtures/controller.line/segments/gradient.png b/test/fixtures/controller.line/segments/gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..74bdef261206944cdaa9754d46f3c2d334dcdc02 GIT binary patch literal 16971 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