diff --git a/__tests__/integration/api-chart-word-cloud-canvas.spec.ts b/__tests__/integration/api-chart-word-cloud-canvas.spec.ts new file mode 100644 index 0000000000..daee6d0882 --- /dev/null +++ b/__tests__/integration/api-chart-word-cloud-canvas.spec.ts @@ -0,0 +1,28 @@ +import { chartWordCloudCanvas as render } from '../plots/api/chart-word-cloud-canvas'; +import './utils/useSnapshotMatchers'; +import { createNodeGCanvas } from './utils/createNodeGCanvas'; +import './utils/useCustomFetch'; + +describe('word cloud canvas', () => { + const canvas = createNodeGCanvas(640, 480); + + it('word cloud should use custom canvas.', async () => { + // This no canvas in JSDOM environment, so it will throw error. + // But it's ok, we just need to test if the ref is called. + let ref; + try { + const rendered = render({ + canvas, + container: document.createElement('div'), + }); + ref = rendered.ref; + await rendered.finished; + } catch (e) { + expect(ref.called).toBe(true); + } + }); + + afterAll(() => { + canvas?.destroy(); + }); +}); diff --git a/__tests__/plots/api/chart-word-cloud-canvas.ts b/__tests__/plots/api/chart-word-cloud-canvas.ts new file mode 100644 index 0000000000..e18ec8b56c --- /dev/null +++ b/__tests__/plots/api/chart-word-cloud-canvas.ts @@ -0,0 +1,31 @@ +import { Chart } from '../../../src'; + +export function chartWordCloudCanvas(context) { + const { container, canvas } = context; + + const chart = new Chart({ + container, + canvas, + }); + + const ref = { called: false }; + + chart.options({ + type: 'wordCloud', + data: { + type: 'fetch', + value: 'data/philosophyWord.json', + }, + layout: { + // random, + canvas: () => { + ref.called = true; + return document.createElement('canvas'); + }, + }, + }); + + const finished = chart.render(); + + return { chart, ref, finished }; +} diff --git a/__tests__/plots/api/index.ts b/__tests__/plots/api/index.ts index 5a17078792..8ff1af5a52 100644 --- a/__tests__/plots/api/index.ts +++ b/__tests__/plots/api/index.ts @@ -52,3 +52,4 @@ export { chartAutoFitHeight } from './chart-auto-fit-height'; export { chartAutoFitWidth } from './chart-auto-fit-width'; export { chartOnLabelClick } from './chart-on-label-click'; export { chartChangeSizeLabelRotate } from './chart-change-size-label-rotate'; +export { chartWordCloudCanvas } from './chart-word-cloud-canvas'; diff --git a/src/data/utils/d3-cloud/index.ts b/src/data/utils/d3-cloud/index.ts index f44ced235d..5421385fa8 100644 --- a/src/data/utils/d3-cloud/index.ts +++ b/src/data/utils/d3-cloud/index.ts @@ -256,10 +256,10 @@ export function tagCloud() { event = cloudDispatch, words = [], timer = null, - timeInterval = Infinity; + timeInterval = Infinity, + canvas = cloudCanvas; const fontStyle = cloudFontNormal; - const canvas = cloudCanvas; const cloud: any = {}; cloud.start = function () { @@ -476,6 +476,10 @@ export function tagCloud() { rotate = functor(_); }; + cloud.canvas = function (_) { + canvas = functor(_); + }; + cloud.spiral = function (_) { spiral = spirals[_] || _; }; diff --git a/src/data/wordCloud.ts b/src/data/wordCloud.ts index 941cd72f85..d1258f90ec 100644 --- a/src/data/wordCloud.ts +++ b/src/data/wordCloud.ts @@ -90,7 +90,16 @@ export type WordCloudOptions = { * If not specified, returns the current random number generator, which defaults to Math.random. */ random: () => number; + + /** + * If specified, sets the spiral used for positioning words. + */ spiral: any; + + /** + * If specified, sets the image mask used for positioning words. + */ + canvas: HTMLCanvasElement; }; const DEFAULT_OPTIONS = { @@ -172,6 +181,7 @@ export const WordCloud: DC> = (options) => { .set('random') .set('text') .set('on') + .set('canvas') .setAsync('imageMask', processImageMask, layout.createMask); layout.words([...data]);