diff --git a/__tests__/integration/issue-5474.spec.ts b/__tests__/integration/issue-5474.spec.ts new file mode 100644 index 0000000000..d51366e32c --- /dev/null +++ b/__tests__/integration/issue-5474.spec.ts @@ -0,0 +1,35 @@ +import { issue5474 as render } from '../plots/bugfix/issue-5474'; +import { createNodeGCanvas } from './utils/createNodeGCanvas'; +import { sleep } from './utils/sleep'; +import './utils/useSnapshotMatchers'; + +describe('issue5474', () => { + const canvas = createNodeGCanvas(800, 500); + + it('issue5474.render() should render chart with labels matching element colors', async () => { + const { chart } = render({ + canvas, + container: document.createElement('div'), + }); + + await chart.render(); + await sleep(20); + + const labels = canvas.document.getElementsByClassName('label'); + expect(labels.length).toBeGreaterThan(0); + + labels.forEach((label) => { + expect(label.style.fill).toBe( + // @ts-ignore + label.__data__.dependentElement.attributes.fill, + ); + }); + + const dir = `${__dirname}/snapshots/bugfix`; + await expect(canvas).toMatchDOMSnapshot(dir, render.name); + }); + + afterAll(() => { + canvas?.destroy(); + }); +}); diff --git a/__tests__/integration/snapshots/bugfix/issue5474.svg b/__tests__/integration/snapshots/bugfix/issue5474.svg new file mode 100644 index 0000000000..9c7a411610 --- /dev/null +++ b/__tests__/integration/snapshots/bugfix/issue5474.svg @@ -0,0 +1,1602 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sports + + + + + + + + + + + + + + + + + + + + Strategy + + + + + + + + + + + + + + + + + + + + Action + + + + + + + + + + + + + + + + + + + + Shooter + + + + + + + + + + + + + + + + + + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sports + + + + + + + Strategy + + + + + + + Action + + + + + + + Shooter + + + + + + + Other + + + + + + + + + genre + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + 50 + + + + + + + 100 + + + + + + + 150 + + + + + + + 200 + + + + + + + 250 + + + + + + + 300 + + + + + + + 350 + + + + + + + + + sold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sports + + + + + + + + + + + + + Strategy + + + + + + + + + + + + + Action + + + + + + + + + + + + + Shooter + + + + + + + + + + + + + Other + + + + + + + + + + + + \ No newline at end of file diff --git a/__tests__/plots/bugfix/index.ts b/__tests__/plots/bugfix/index.ts index 8e2caa72e2..5fb5c75b2f 100644 --- a/__tests__/plots/bugfix/index.ts +++ b/__tests__/plots/bugfix/index.ts @@ -2,3 +2,4 @@ export { issue6396 } from './issue-6396'; export { issue6399 } from './issue-6399'; export { issueChart2719 } from './issue-chart-2719'; export { issue6020 } from './issue-6020'; +export { issue5474 } from './issue-5474'; diff --git a/__tests__/plots/bugfix/issue-5474.ts b/__tests__/plots/bugfix/issue-5474.ts new file mode 100644 index 0000000000..70d505fa35 --- /dev/null +++ b/__tests__/plots/bugfix/issue-5474.ts @@ -0,0 +1,37 @@ +import { Chart } from '../../../src'; + +export function issue5474(context) { + const { container, canvas, callback } = context; + + const chart = new Chart({ + container: container, + autoFit: true, + insetRight: 10, + canvas, + }); + + if (callback) { + callback(chart); + } else { + chart + .interval() + .data([ + { genre: 'Sports', sold: 0 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]) + .encode('x', 'genre') + .encode('y', 'sold') + .encode('color', 'genre') + .label({ + text: 'genre', + fill: (_, i, array, d) => d.elementStyle.fill, + }); + } + + chart.render(); + + return { chart }; +} diff --git a/site/docs/spec/label/overview.zh.md b/site/docs/spec/label/overview.zh.md index c7408b5bd0..e327ef3c85 100644 --- a/site/docs/spec/label/overview.zh.md +++ b/site/docs/spec/label/overview.zh.md @@ -127,7 +127,7 @@ chart d, i, data, - { channel }, // 聚合图形的样式 + { channel, elementStyle }, // 聚合图形的样式 & label依赖元素的样式 ) => (channel.y[i] < 11700 ? '#E49361' : '#4787F7'), ); ``` diff --git a/src/runtime/plot.ts b/src/runtime/plot.ts index a5ee20e6be..ae1725b8c5 100644 --- a/src/runtime/plot.ts +++ b/src/runtime/plot.ts @@ -1197,7 +1197,9 @@ function plotLabel( return elements.flatMap((e) => { const L = getLabels(options, i, e); L.forEach((l) => { - labelShapeFunction.set(l, shapeFunction); + labelShapeFunction.set(l, (data) => + shapeFunction({ ...data, elementStyle: e.attributes }), + ); labelDescriptor.set(l, labelOption); }); return L; @@ -1365,11 +1367,17 @@ function createLabelShapeFunction( style: abstractStyle, render, selector, + elementStyle, ...abstractOptions } = options; + const visualOptions = mapObject( { ...abstractOptions, ...abstractStyle } as Record, - (d) => valueOf(d, datum, index, abstractData, { channel }), + (d) => + valueOf(d, datum, index, abstractData, { + channel: { ...channel }, + elementStyle, + }), ); const { shape = defaultLabelShape, text, ...style } = visualOptions; const f = typeof formatter === 'string' ? format(formatter) : formatter; @@ -1393,7 +1401,7 @@ function valueOf( datum: Record, i: number, data: Record, - options: { channel: Record }, + options: { channel: Record; elementStyle?: Record }, ) { if (typeof value === 'function') return value(datum, i, data, options); if (typeof value !== 'string') return value;