From 9b10019f9913be35f11756150544526a0bdda4ec Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Wed, 21 Oct 2020 15:16:44 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fix(word-cloud):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E9=A2=9C=E8=89=B2=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plots/word-cloud/index.ts | 7 +++++-- src/plots/word-cloud/shapes/word-cloud.ts | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plots/word-cloud/index.ts b/src/plots/word-cloud/index.ts index a5bacdcb27..efe80d0d54 100644 --- a/src/plots/word-cloud/index.ts +++ b/src/plots/word-cloud/index.ts @@ -73,8 +73,11 @@ export class WordCloud extends Plot { */ protected triggerResize() { if (!this.chart.destroyed) { - // 当整个词云图图表的宽高信息发生变化时,每个词语的坐标需要重新 - // 需要重新执行 adaptor,执行词云图的布局函数,不然会出现布局错乱,如相邻词语重叠的情况。 + // 这里解决了重渲染时字体变的透明的问题 + this.chart.clear(); + // 当整个词云图图表的宽高信息发生变化时,每个词语的坐标 + // 需要重新执行 adaptor,执行词云图的布局函数,不然会出现布局错乱, + // 如相邻词语重叠的情况。 this.execAdaptor(); // 执行父类的方法 super.triggerResize(); diff --git a/src/plots/word-cloud/shapes/word-cloud.ts b/src/plots/word-cloud/shapes/word-cloud.ts index 41ea50a74d..37538e22b1 100644 --- a/src/plots/word-cloud/shapes/word-cloud.ts +++ b/src/plots/word-cloud/shapes/word-cloud.ts @@ -28,8 +28,6 @@ registerShape('point', 'word-cloud', { function getTextAttrs(cfg: Config): ShapeAttrs { return { - ...cfg.defaultStyle, - ...cfg.style, fontSize: cfg.data.size, text: cfg.data.text, textAlign: 'center', From 86e99142191f0a00304d08b0fa0539569ee86ce2 Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Wed, 21 Oct 2020 19:21:35 +0800 Subject: [PATCH 2/9] fix(word-cloud): fix tooltip and add demo of custom tooltip --- .../word-cloud/basic/demo/custom-tooltip.ts | 32 +++++++++++ examples/word-cloud/basic/demo/meta.json | 8 +++ src/plots/word-cloud/adaptor.ts | 2 +- src/plots/word-cloud/index.ts | 11 +++- src/plots/word-cloud/types.ts | 4 +- src/utils/transform/word-cloud.ts | 53 ++++++++++--------- 6 files changed, 80 insertions(+), 30 deletions(-) create mode 100644 examples/word-cloud/basic/demo/custom-tooltip.ts diff --git a/examples/word-cloud/basic/demo/custom-tooltip.ts b/examples/word-cloud/basic/demo/custom-tooltip.ts new file mode 100644 index 0000000000..32a52172e5 --- /dev/null +++ b/examples/word-cloud/basic/demo/custom-tooltip.ts @@ -0,0 +1,32 @@ +import { WordCloud } from '@antv/g2plot'; + +fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/antv-keywords.json') + .then((res) => res.json()) + .then((data) => { + const wordCloud = new WordCloud('container', { + data, + width: 600, + height: 400, + wordField: 'name', + weightField: 'value', + imageMask: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*07tdTIOmvlYAAAAAAAAAAABkARQnAQ', + wordStyle: { + fontFamily: 'Verdana', + fontSize: [8, 32], + }, + tooltip: { + customContent(_, data) { + if (!data.length) return; + return `

title

+
  • + + + ${data[0]?.data.text}:${data[0]?.data.value} + +
  • `; + }, + }, + }); + + wordCloud.render(); + }); diff --git a/examples/word-cloud/basic/demo/meta.json b/examples/word-cloud/basic/demo/meta.json index 1a5a4ff998..08e7918dd0 100644 --- a/examples/word-cloud/basic/demo/meta.json +++ b/examples/word-cloud/basic/demo/meta.json @@ -35,6 +35,14 @@ "en": "Word Cloud chart - image mask base64" }, "screenshot": "https://gw.alipayobjects.com/mdn/rms_d314dd/afts/img/A*qkYyQqFTU4YAAAAAAAAAAAAAARQnAQ" + }, + { + "filename": "custom-tooltip.ts", + "title": { + "zh": "词云图-自定义Tooltip", + "en": "Word Cloud chart - custom tooltip" + }, + "screenshot": "https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*id4CSZIMCtsAAAAAAAAAAABkARQnAQ" } ] } diff --git a/src/plots/word-cloud/adaptor.ts b/src/plots/word-cloud/adaptor.ts index 1879716531..c7260e2f2c 100644 --- a/src/plots/word-cloud/adaptor.ts +++ b/src/plots/word-cloud/adaptor.ts @@ -13,7 +13,7 @@ function geometry(params: Params): Params { const data = transform(params); chart.data(data); - chart.point().position('x*y').shape('word-cloud'); + chart.point().position('_x*_y').shape('word-cloud'); return params; } diff --git a/src/plots/word-cloud/index.ts b/src/plots/word-cloud/index.ts index efe80d0d54..90dbd39456 100644 --- a/src/plots/word-cloud/index.ts +++ b/src/plots/word-cloud/index.ts @@ -1,7 +1,7 @@ import { deepMix } from '@antv/util'; import { Plot } from '../../core/plot'; import { Adaptor } from '../../core/adaptor'; -import { WordCloudOptions } from './types'; +import { DataItem, WordCloudOptions } from './types'; import { adaptor } from './adaptor'; import { processImageMask } from './utils'; // 注册的shape @@ -23,6 +23,15 @@ export class WordCloud extends Plot { showTitle: false, showMarkers: false, showCrosshairs: false, + customContent(_, data: { data: DataItem; mappingData: any }[]) { + if (!data.length) return; + return `
  • + + + ${data[0]?.data.text}:${data[0]?.data.value} + +
  • `; + }, }, wordStyle: { fontFamily: 'Verdana', diff --git a/src/plots/word-cloud/types.ts b/src/plots/word-cloud/types.ts index 721a85a1ff..30942814f2 100644 --- a/src/plots/word-cloud/types.ts +++ b/src/plots/word-cloud/types.ts @@ -30,9 +30,9 @@ export type DataItem = Row & { /** 单词所占盒子的高度 */ height?: number; /** x 轴坐标 */ - x?: number; + _x?: number; /** y 轴坐标 */ - y?: number; + _y?: number; }; /** 词云字体样式 */ diff --git a/src/utils/transform/word-cloud.ts b/src/utils/transform/word-cloud.ts index e755c85147..17a4041d3f 100644 --- a/src/utils/transform/word-cloud.ts +++ b/src/utils/transform/word-cloud.ts @@ -76,23 +76,23 @@ export function transform(data: Data, options: Options) { { x: options.size[0], y: options.size[1] }, ]; tags.forEach((tag) => { - tag.x += options.size[0] / 2; - tag.y += options.size[1] / 2; + tag._x += options.size[0] / 2; + tag._y += options.size[1] / 2; }); const [w, h] = options.size; const hasImage = result.hasImage; tags.push({ text: '', value: 0, - x: hasImage ? 0 : bounds[0].x, - y: hasImage ? 0 : bounds[0].y, + _x: hasImage ? 0 : bounds[0].x, + _y: hasImage ? 0 : bounds[0].y, opacity: 0, }); tags.push({ text: '', value: 0, - x: hasImage ? w : bounds[1].x, - y: hasImage ? h : bounds[1].y, + _x: hasImage ? w : bounds[1].x, + _y: hasImage ? h : bounds[1].y, opacity: 0, }); @@ -237,11 +237,11 @@ function cloudCollide(tag, board, sw) { sw >>= 5; const sprite = tag.sprite, w = tag.width >> 5, - lx = tag.x - (w << 4), + lx = tag._x - (w << 4), sx = lx & 0x7f, msx = 32 - sx, h = tag.y1 - tag.y0; - let x = (tag.y + tag.y0) * sw + (lx >> 5), + let x = (tag._y + tag.y0) * sw + (lx >> 5), last; for (let j = 0; j < h; j++) { last = 0; @@ -256,14 +256,14 @@ function cloudCollide(tag, board, sw) { function cloudBounds(bounds, d) { const b0 = bounds[0], b1 = bounds[1]; - if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0; - if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0; - if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1; - if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1; + if (d._x + d.x0 < b0.x) b0.x = d._x + d.x0; + if (d._y + d.y0 < b0.y) b0.y = d._y + d.y0; + if (d._x + d.x1 > b1.x) b1.x = d._x + d.x1; + if (d._y + d.y1 > b1.y) b1.y = d._y + d.y1; } function collideRects(a, b) { - return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y; + return a._x + a.x1 > b[0].x && a._x + a.x0 < b[1].x && a._y + a.y1 > b[0].y && a._y + a.y0 < b[1].y; } function archimedeanSpiral(size) { @@ -380,8 +380,8 @@ function tagCloud() { const start = Date.now(); while (Date.now() - start < timeInterval && ++i < n) { const d = data[i]; - d.x = (width * (random() + 0.5)) >> 1; - d.y = (height * (random() + 0.5)) >> 1; + d._x = (width * (random() + 0.5)) >> 1; + d._y = (height * (random() + 0.5)) >> 1; cloudSprite(contextAndRatio, d, data, i); if (d.hasText && place(board, d, bounds)) { tags.push(d); @@ -392,13 +392,13 @@ function tagCloud() { } } else { bounds = [ - { x: d.x + d.x0, y: d.y + d.y0 }, - { x: d.x + d.x1, y: d.y + d.y1 }, + { x: d._x + d.x0, y: d._y + d.y0 }, + { x: d._x + d.x1, y: d._y + d.y1 }, ]; } // Temporary hack - d.x -= size[0] >> 1; - d.y -= size[1] >> 1; + d._x -= size[0] >> 1; + d._y -= size[1] >> 1; } } cloud._tags = tags; @@ -422,8 +422,8 @@ function tagCloud() { function place(board, tag, bounds) { // const perimeter = [{ x: 0, y: 0 }, { x: size[0], y: size[1] }], - const startX = tag.x, - startY = tag.y, + const startX = tag._x, + startY = tag._y, maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), s = spiral(size), dt = random() < 0.5 ? 1 : -1; @@ -438,22 +438,23 @@ function tagCloud() { if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break; - tag.x = startX + dx; - tag.y = startY + dy; + tag._x = startX + dx; + tag._y = startY + dy; - if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue; + if (tag._x + tag.x0 < 0 || tag._y + tag.y0 < 0 || tag._x + tag.x1 > size[0] || tag._y + tag.y1 > size[1]) + continue; // TODO only check for collisions within current bounds. if (!bounds || !cloudCollide(tag, board, size[0])) { if (!bounds || collideRects(tag, bounds)) { const sprite = tag.sprite, w = tag.width >> 5, sw = size[0] >> 5, - lx = tag.x - (w << 4), + lx = tag._x - (w << 4), sx = lx & 0x7f, msx = 32 - sx, h = tag.y1 - tag.y0; let last, - x = (tag.y + tag.y0) * sw + (lx >> 5); + x = (tag._y + tag.y0) * sw + (lx >> 5); for (let j = 0; j < h; j++) { last = 0; for (let i = 0; i <= w; i++) { From c0dba1cf8f212ceb21afef338e524d7709365ff8 Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Wed, 21 Oct 2020 19:48:52 +0800 Subject: [PATCH 3/9] chore: modify test --- __tests__/unit/plots/word-cloud/index-spec.ts | 4 ++-- __tests__/unit/utils/transform/word-cloud-spec.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/__tests__/unit/plots/word-cloud/index-spec.ts b/__tests__/unit/plots/word-cloud/index-spec.ts index e9335469f5..7feb057b08 100644 --- a/__tests__/unit/plots/word-cloud/index-spec.ts +++ b/__tests__/unit/plots/word-cloud/index-spec.ts @@ -24,8 +24,8 @@ describe('word-cloud', () => { // x & y expect(positionFields).toHaveLength(2); // 数据经过 DataSet 处理过,这里是处理之后的数据中的 x 和 y 字段 - expect(positionFields[0]).toBe('x'); - expect(positionFields[1]).toBe('y'); + expect(positionFields[0]).toBe('_x'); + expect(positionFields[1]).toBe('_y'); }); it('imageMask', () => { diff --git a/__tests__/unit/utils/transform/word-cloud-spec.ts b/__tests__/unit/utils/transform/word-cloud-spec.ts index ee0955a2df..339848bdff 100644 --- a/__tests__/unit/utils/transform/word-cloud-spec.ts +++ b/__tests__/unit/utils/transform/word-cloud-spec.ts @@ -38,8 +38,8 @@ function basicCommon(v: DataItem) { expect(typeof v.padding).toBe('number'); expect(typeof v.width).toBe('number'); expect(typeof v.height).toBe('number'); - expect(typeof v.x).toBe('number'); - expect(typeof v.y).toBe('number'); + expect(typeof v._x).toBe('number'); + expect(typeof v._y).toBe('number'); } describe('word-cloud', () => { @@ -51,6 +51,8 @@ describe('word-cloud', () => { function removeXY(v) { delete v.x; delete v.y; + delete v._x; + delete v._y; } const result1 = wordCloud(data, options as any); const result2 = dv.rows; From 604d5f4319c800fcde0092734db5b8c326737193 Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Wed, 21 Oct 2020 21:25:11 +0800 Subject: [PATCH 4/9] =?UTF-8?q?chore:=20=E5=A4=84=E7=90=86=E4=B9=8B?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E6=95=B0=E6=8D=AE=E4=B8=8D=E4=B8=8E=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=9A=84=E6=95=B0=E6=8D=AE=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/unit/plots/word-cloud/index-spec.ts | 4 +- .../unit/utils/transform/word-cloud-spec.ts | 7 +-- src/plots/word-cloud/adaptor.ts | 6 +- src/plots/word-cloud/types.ts | 4 +- src/utils/transform/word-cloud.ts | 62 +++++++++---------- 5 files changed, 39 insertions(+), 44 deletions(-) diff --git a/__tests__/unit/plots/word-cloud/index-spec.ts b/__tests__/unit/plots/word-cloud/index-spec.ts index 7feb057b08..e9335469f5 100644 --- a/__tests__/unit/plots/word-cloud/index-spec.ts +++ b/__tests__/unit/plots/word-cloud/index-spec.ts @@ -24,8 +24,8 @@ describe('word-cloud', () => { // x & y expect(positionFields).toHaveLength(2); // 数据经过 DataSet 处理过,这里是处理之后的数据中的 x 和 y 字段 - expect(positionFields[0]).toBe('_x'); - expect(positionFields[1]).toBe('_y'); + expect(positionFields[0]).toBe('x'); + expect(positionFields[1]).toBe('y'); }); it('imageMask', () => { diff --git a/__tests__/unit/utils/transform/word-cloud-spec.ts b/__tests__/unit/utils/transform/word-cloud-spec.ts index 339848bdff..fd0a52a46b 100644 --- a/__tests__/unit/utils/transform/word-cloud-spec.ts +++ b/__tests__/unit/utils/transform/word-cloud-spec.ts @@ -22,7 +22,6 @@ const data = ['Hello', 'world', 'normally', 'you', 'want', 'more', 'words', 'tha return { text: d, value: 5 + Math.random() * 10, - test: 'haha', }; }); @@ -38,8 +37,8 @@ function basicCommon(v: DataItem) { expect(typeof v.padding).toBe('number'); expect(typeof v.width).toBe('number'); expect(typeof v.height).toBe('number'); - expect(typeof v._x).toBe('number'); - expect(typeof v._y).toBe('number'); + expect(typeof v.x).toBe('number'); + expect(typeof v.y).toBe('number'); } describe('word-cloud', () => { @@ -51,8 +50,6 @@ describe('word-cloud', () => { function removeXY(v) { delete v.x; delete v.y; - delete v._x; - delete v._y; } const result1 = wordCloud(data, options as any); const result2 = dv.rows; diff --git a/src/plots/word-cloud/adaptor.ts b/src/plots/word-cloud/adaptor.ts index c7260e2f2c..f9e3ca7c88 100644 --- a/src/plots/word-cloud/adaptor.ts +++ b/src/plots/word-cloud/adaptor.ts @@ -13,7 +13,7 @@ function geometry(params: Params): Params { const data = transform(params); chart.data(data); - chart.point().position('_x*_y').shape('word-cloud'); + chart.point().position('x*y').shape('word-cloud'); return params; } @@ -24,10 +24,10 @@ function geometry(params: Params): Params { */ function color(params: Params): Params { const { chart, options } = params; - const { wordField, color } = options; + const { color } = options; const geometry = findGeometry(chart, 'point'); - geometry.color(wordField, color); + geometry.color('text', color); return params; } diff --git a/src/plots/word-cloud/types.ts b/src/plots/word-cloud/types.ts index 30942814f2..721a85a1ff 100644 --- a/src/plots/word-cloud/types.ts +++ b/src/plots/word-cloud/types.ts @@ -30,9 +30,9 @@ export type DataItem = Row & { /** 单词所占盒子的高度 */ height?: number; /** x 轴坐标 */ - _x?: number; + x?: number; /** y 轴坐标 */ - _y?: number; + y?: number; }; /** 词云字体样式 */ diff --git a/src/utils/transform/word-cloud.ts b/src/utils/transform/word-cloud.ts index 17a4041d3f..dd9ea45b6d 100644 --- a/src/utils/transform/word-cloud.ts +++ b/src/utils/transform/word-cloud.ts @@ -60,11 +60,10 @@ export function transform(data: Data, options: Options) { if (!isString(text) || !isString(value)) { throw new TypeError('Invalid fields: must be an array with 2 strings (e.g. [ "text", "value" ])!'); } - const words = data.map((row) => { - row.text = row[text]; - row.value = row[value]; - return row; - }); + const words = data.map((row) => ({ + text: row[text], + value: row[value], + })); layout.words(words); if (options.imageMask) { layout.createMask(options.imageMask); @@ -76,23 +75,23 @@ export function transform(data: Data, options: Options) { { x: options.size[0], y: options.size[1] }, ]; tags.forEach((tag) => { - tag._x += options.size[0] / 2; - tag._y += options.size[1] / 2; + tag.x += options.size[0] / 2; + tag.y += options.size[1] / 2; }); const [w, h] = options.size; const hasImage = result.hasImage; tags.push({ text: '', value: 0, - _x: hasImage ? 0 : bounds[0].x, - _y: hasImage ? 0 : bounds[0].y, + x: hasImage ? 0 : bounds[0].x, + y: hasImage ? 0 : bounds[0].y, opacity: 0, }); tags.push({ text: '', value: 0, - _x: hasImage ? w : bounds[1].x, - _y: hasImage ? h : bounds[1].y, + x: hasImage ? w : bounds[1].x, + y: hasImage ? h : bounds[1].y, opacity: 0, }); @@ -237,11 +236,11 @@ function cloudCollide(tag, board, sw) { sw >>= 5; const sprite = tag.sprite, w = tag.width >> 5, - lx = tag._x - (w << 4), + lx = tag.x - (w << 4), sx = lx & 0x7f, msx = 32 - sx, h = tag.y1 - tag.y0; - let x = (tag._y + tag.y0) * sw + (lx >> 5), + let x = (tag.y + tag.y0) * sw + (lx >> 5), last; for (let j = 0; j < h; j++) { last = 0; @@ -256,14 +255,14 @@ function cloudCollide(tag, board, sw) { function cloudBounds(bounds, d) { const b0 = bounds[0], b1 = bounds[1]; - if (d._x + d.x0 < b0.x) b0.x = d._x + d.x0; - if (d._y + d.y0 < b0.y) b0.y = d._y + d.y0; - if (d._x + d.x1 > b1.x) b1.x = d._x + d.x1; - if (d._y + d.y1 > b1.y) b1.y = d._y + d.y1; + if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0; + if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0; + if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1; + if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1; } function collideRects(a, b) { - return a._x + a.x1 > b[0].x && a._x + a.x0 < b[1].x && a._y + a.y1 > b[0].y && a._y + a.y0 < b[1].y; + return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y; } function archimedeanSpiral(size) { @@ -380,8 +379,8 @@ function tagCloud() { const start = Date.now(); while (Date.now() - start < timeInterval && ++i < n) { const d = data[i]; - d._x = (width * (random() + 0.5)) >> 1; - d._y = (height * (random() + 0.5)) >> 1; + d.x = (width * (random() + 0.5)) >> 1; + d.y = (height * (random() + 0.5)) >> 1; cloudSprite(contextAndRatio, d, data, i); if (d.hasText && place(board, d, bounds)) { tags.push(d); @@ -392,13 +391,13 @@ function tagCloud() { } } else { bounds = [ - { x: d._x + d.x0, y: d._y + d.y0 }, - { x: d._x + d.x1, y: d._y + d.y1 }, + { x: d.x + d.x0, y: d.y + d.y0 }, + { x: d.x + d.x1, y: d.y + d.y1 }, ]; } // Temporary hack - d._x -= size[0] >> 1; - d._y -= size[1] >> 1; + d.x -= size[0] >> 1; + d.y -= size[1] >> 1; } } cloud._tags = tags; @@ -422,8 +421,8 @@ function tagCloud() { function place(board, tag, bounds) { // const perimeter = [{ x: 0, y: 0 }, { x: size[0], y: size[1] }], - const startX = tag._x, - startY = tag._y, + const startX = tag.x, + startY = tag.y, maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), s = spiral(size), dt = random() < 0.5 ? 1 : -1; @@ -438,23 +437,22 @@ function tagCloud() { if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break; - tag._x = startX + dx; - tag._y = startY + dy; + tag.x = startX + dx; + tag.y = startY + dy; - if (tag._x + tag.x0 < 0 || tag._y + tag.y0 < 0 || tag._x + tag.x1 > size[0] || tag._y + tag.y1 > size[1]) - continue; + if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue; // TODO only check for collisions within current bounds. if (!bounds || !cloudCollide(tag, board, size[0])) { if (!bounds || collideRects(tag, bounds)) { const sprite = tag.sprite, w = tag.width >> 5, sw = size[0] >> 5, - lx = tag._x - (w << 4), + lx = tag.x - (w << 4), sx = lx & 0x7f, msx = 32 - sx, h = tag.y1 - tag.y0; let last, - x = (tag._y + tag.y0) * sw + (lx >> 5); + x = (tag.y + tag.y0) * sw + (lx >> 5); for (let j = 0; j < h; j++) { last = 0; for (let i = 0; i <= w; i++) { From f1ee48f5c15b4f3b32fba7d8f09d4ebb5359a4bf Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Thu, 22 Oct 2020 12:07:58 +0800 Subject: [PATCH 5/9] feat(word-cloud): add colorField option --- __tests__/bugs/issue-1754-spec.ts | 0 __tests__/unit/plots/word-cloud/color-spec.ts | 68 +++++++++++++++++++ docs/manual/plots/word-cloud.en.md | 8 +++ docs/manual/plots/word-cloud.zh.md | 10 ++- examples/word-cloud/basic/demo/color-field.ts | 21 ++++++ examples/word-cloud/basic/demo/meta.json | 8 +++ src/plots/word-cloud/adaptor.ts | 12 +++- src/plots/word-cloud/types.ts | 2 + 8 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 __tests__/bugs/issue-1754-spec.ts create mode 100644 __tests__/unit/plots/word-cloud/color-spec.ts create mode 100644 examples/word-cloud/basic/demo/color-field.ts diff --git a/__tests__/bugs/issue-1754-spec.ts b/__tests__/bugs/issue-1754-spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/__tests__/unit/plots/word-cloud/color-spec.ts b/__tests__/unit/plots/word-cloud/color-spec.ts new file mode 100644 index 0000000000..45100fa2bb --- /dev/null +++ b/__tests__/unit/plots/word-cloud/color-spec.ts @@ -0,0 +1,68 @@ +import { WordCloud } from '../../../../src'; +import { CountryEconomy } from '../../../data/country-economy'; +import { createDiv } from '../../../utils/dom'; + +describe('word-cloud color option', () => { + it('default', () => { + const cloud = new WordCloud(createDiv(), { + width: 400, + height: 300, + data: CountryEconomy, + wordField: 'Country', + weightField: 'GDP', + }); + + cloud.render(); + + const field = cloud.chart.geometries[0].getGroupFields()[0]; + expect(field).toBe('text'); + }); + + it('wordField', () => { + const cloud = new WordCloud(createDiv(), { + width: 400, + height: 300, + data: CountryEconomy, + wordField: 'Country', + weightField: 'GDP', + colorField: 'Country', // wordField 字段值 + }); + + cloud.render(); + + const field = cloud.chart.geometries[0].getGroupFields()[0]; + expect(field).toBe('text'); + }); + + it('weightField', () => { + const cloud = new WordCloud(createDiv(), { + width: 400, + height: 300, + data: CountryEconomy, + wordField: 'Country', + weightField: 'GDP', + colorField: 'GDP', // weightField 字段值 + }); + + cloud.render(); + + const field = cloud.chart.geometries[0].getGroupFields()[0]; + expect(field).toBe('value'); + }); + + it('x', () => { + const cloud = new WordCloud(createDiv(), { + width: 400, + height: 300, + data: CountryEconomy, + wordField: 'Country', + weightField: 'GDP', + colorField: 'x', + }); + + cloud.render(); + + const field = cloud.chart.geometries[0].getGroupFields()[0]; + expect(field).toBe('x'); + }); +}); diff --git a/docs/manual/plots/word-cloud.en.md b/docs/manual/plots/word-cloud.en.md index d9b57fec0f..c6d934fcaa 100644 --- a/docs/manual/plots/word-cloud.en.md +++ b/docs/manual/plots/word-cloud.en.md @@ -37,6 +37,14 @@ order: 0 默认配置: 无 +#### colorField + +**可选**, _string_ + +功能描述: 根据该字段进行颜色映射 + +默认配置: wordField 字段的值 + #### timeInterval **可选**, _number_ diff --git a/docs/manual/plots/word-cloud.zh.md b/docs/manual/plots/word-cloud.zh.md index f0fa71ae32..7d7f3820fe 100644 --- a/docs/manual/plots/word-cloud.zh.md +++ b/docs/manual/plots/word-cloud.zh.md @@ -2,7 +2,7 @@ title: 词云图 order: 0 --- - + ## 配置属性 ### 图表容器 @@ -37,6 +37,14 @@ order: 0 默认配置: 无 +#### colorField + +**可选**, _string_ + +功能描述: 根据该字段进行颜色映射 + +默认配置: wordField 字段的值 + #### timeInterval **可选**, _number_ diff --git a/examples/word-cloud/basic/demo/color-field.ts b/examples/word-cloud/basic/demo/color-field.ts new file mode 100644 index 0000000000..e75cac5c5f --- /dev/null +++ b/examples/word-cloud/basic/demo/color-field.ts @@ -0,0 +1,21 @@ +import { WordCloud } from '@antv/g2plot'; + +fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/antv-keywords.json') + .then((res) => res.json()) + .then((data) => { + const wordCloud = new WordCloud('container', { + data, + width: 600, + height: 400, + wordField: 'name', + weightField: 'value', + colorField: 'value', + imageMask: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*07tdTIOmvlYAAAAAAAAAAABkARQnAQ', + wordStyle: { + fontFamily: 'Verdana', + fontSize: [8, 32], + }, + }); + + wordCloud.render(); + }); diff --git a/examples/word-cloud/basic/demo/meta.json b/examples/word-cloud/basic/demo/meta.json index 08e7918dd0..bbd91014b6 100644 --- a/examples/word-cloud/basic/demo/meta.json +++ b/examples/word-cloud/basic/demo/meta.json @@ -43,6 +43,14 @@ "en": "Word Cloud chart - custom tooltip" }, "screenshot": "https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*id4CSZIMCtsAAAAAAAAAAABkARQnAQ" + }, + { + "filename": "color-field.ts", + "title": { + "zh": "词云图-colorField", + "en": "Word Cloud chart - colorField" + }, + "screenshot": "https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*id4CSZIMCtsAAAAAAAAAAABkARQnAQ" } ] } diff --git a/src/plots/word-cloud/adaptor.ts b/src/plots/word-cloud/adaptor.ts index f9e3ca7c88..287e4fc7a0 100644 --- a/src/plots/word-cloud/adaptor.ts +++ b/src/plots/word-cloud/adaptor.ts @@ -24,10 +24,16 @@ function geometry(params: Params): Params { */ function color(params: Params): Params { const { chart, options } = params; - const { color } = options; + const { color, colorField, wordField, weightField } = options; const geometry = findGeometry(chart, 'point'); - - geometry.color('text', color); + // 最终的数据中 wordField 和 weightField 对应的字段值 + // 会转换成 'text' 和 'value' + const fieldMap = { + [wordField]: 'text', + [weightField]: 'value', + }; + + geometry.color(colorField ? fieldMap[colorField] || colorField : 'text', color); return params; } diff --git a/src/plots/word-cloud/types.ts b/src/plots/word-cloud/types.ts index 721a85a1ff..dd8426726b 100644 --- a/src/plots/word-cloud/types.ts +++ b/src/plots/word-cloud/types.ts @@ -61,6 +61,8 @@ export interface WordCloudOptions extends Options { readonly wordField: string; /** 词条权重字段 */ readonly weightField: string; + /** 根据该字段进行颜色映射 */ + readonly colorField?: string; /** 遮罩图片实例,可以是图片 URL 或者 base64 */ readonly imageMask?: HTMLImageElement | string; /** 最大执行时间 */ From c51587b39937b114787443bffedb312b0e5d4400 Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Thu, 22 Oct 2020 13:46:30 +0800 Subject: [PATCH 6/9] chore: add test for 1754 --- __tests__/bugs/issue-1754-spec.ts | 35 +++++++++++++++++++++++++++++++ src/plots/word-cloud/index.ts | 18 +++++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/__tests__/bugs/issue-1754-spec.ts b/__tests__/bugs/issue-1754-spec.ts index e69de29bb2..90b887a2cc 100644 --- a/__tests__/bugs/issue-1754-spec.ts +++ b/__tests__/bugs/issue-1754-spec.ts @@ -0,0 +1,35 @@ +import { TooltipCfg } from '@antv/g2/lib/interface'; +import { WordCloud } from '../../src'; +import { CountryEconomy } from '../data/country-economy'; +import { createDiv } from '../utils/dom'; + +describe('issue 1754', () => { + it('customContent', () => { + const cloud = new WordCloud(createDiv(), { + width: 400, + height: 300, + data: CountryEconomy, + wordField: 'Country', + weightField: 'GDP', + }); + + const data = [ + { + data: { text: 'name', value: 'weight' }, + mappingData: { color: 'red' }, + }, + ]; + const result = + '
  • ' + + '' + + '' + + 'name:weight' + + '' + + '
  • '; + + cloud.render(); + + const customContent = (cloud.chart.getOptions().tooltip as TooltipCfg).customContent; + expect(customContent(undefined, data)).toBe(result); + }); +}); diff --git a/src/plots/word-cloud/index.ts b/src/plots/word-cloud/index.ts index 90dbd39456..f828e0db78 100644 --- a/src/plots/word-cloud/index.ts +++ b/src/plots/word-cloud/index.ts @@ -23,14 +23,18 @@ export class WordCloud extends Plot { showTitle: false, showMarkers: false, showCrosshairs: false, - customContent(_, data: { data: DataItem; mappingData: any }[]) { + customContent(_, data: { data: DataItem; mappingData: { color: string } }[]) { if (!data.length) return; - return `
  • - - - ${data[0]?.data.text}:${data[0]?.data.value} - -
  • `; + // 不完全采用模板字符串,是为了去掉换行符和部分空格, + // 便于测试。 + return ( + '
  • ' + + `` + + '' + + `${data[0]?.data.text}:${data[0]?.data.value}` + + '' + + '
  • ' + ); }, }, wordStyle: { From 52906f395ca210fa3defc93350ccca5581c7dfb4 Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Thu, 22 Oct 2020 16:45:39 +0800 Subject: [PATCH 7/9] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plots/word-cloud/adaptor.ts | 99 ++++++----------------- src/plots/word-cloud/index.ts | 4 +- src/plots/word-cloud/shapes/word-cloud.ts | 4 +- src/plots/word-cloud/types.ts | 19 +++-- src/plots/word-cloud/utils.ts | 26 ++++-- src/utils/transform/word-cloud.ts | 58 ++++++------- 6 files changed, 87 insertions(+), 123 deletions(-) diff --git a/src/plots/word-cloud/adaptor.ts b/src/plots/word-cloud/adaptor.ts index 287e4fc7a0..be3b23b835 100644 --- a/src/plots/word-cloud/adaptor.ts +++ b/src/plots/word-cloud/adaptor.ts @@ -1,6 +1,8 @@ +import { deepMix } from '@antv/util'; import { Params } from '../../core/adaptor'; import { tooltip, interaction, animation, theme, scale, state } from '../../adaptor/common'; -import { flow, findGeometry } from '../../utils'; +import { flow } from '../../utils'; +import { point } from '../../adaptor/geometries'; import { WordCloudOptions } from './types'; import { transform } from './utils'; @@ -9,31 +11,32 @@ import { transform } from './utils'; * @param params */ function geometry(params: Params): Params { - const { chart } = params; + const { chart, options } = params; + const { colorField, color } = options; const data = transform(params); chart.data(data); - chart.point().position('x*y').shape('word-cloud'); - - return params; -} -/** - * color 配置处理 - * @param params - */ -function color(params: Params): Params { - const { chart, options } = params; - const { color, colorField, wordField, weightField } = options; - const geometry = findGeometry(chart, 'point'); - // 最终的数据中 wordField 和 weightField 对应的字段值 - // 会转换成 'text' 和 'value' - const fieldMap = { - [wordField]: 'text', - [weightField]: 'value', - }; + const p = deepMix({}, params, { + options: { + xField: 'x', + yField: 'y', + // 给 seriesField 一个默认值,否则它为空时 + // 每个词语的颜色会显示成白色。 + seriesField: colorField ? 'color' : 'text', + point: { + color, + shape: 'word-cloud', + }, + }, + }); + + const { ext } = point(p); + ext.geometry.label(false); - geometry.color(colorField ? fieldMap[colorField] || colorField : 'text', color); + chart.coordinate().reflect('y'); + chart.axis(false); + chart.legend(false); return params; } @@ -51,58 +54,6 @@ function meta(params: Params): Params { )(params); } -/** - * coord 配置 - * @param params - */ -function coord(params: Params): Params { - const { chart } = params; - - chart.coordinate().reflect('y'); - - return params; -} - -/** - * axis 配置 - * 词云图不显示轴信息 - * @param params - */ -function axis(params: Params): Params { - const { chart } = params; - - chart.axis(false); - - return params; -} - -/** - * label 配置 - * 词云图不显示 label 信息 - * @param params - */ -function label(params: Params): Params { - const { chart } = params; - const geometry = findGeometry(chart, 'point'); - - geometry.label(false); - - return params; -} - -/** - * legend 配置 - * 词云图不显示 legend 信息 - * @param params - */ -function legend(params: Params): Params { - const { chart } = params; - - chart.legend(false); - - return params; -} - /** * 词云图适配器 * @param chart @@ -110,5 +61,5 @@ function legend(params: Params): Params { */ export function adaptor(params: Params) { // flow 的方式处理所有的配置到 G2 API - flow(geometry, meta, coord, axis, label, color, legend, tooltip, interaction, animation, theme, state)(params); + flow(geometry, meta, tooltip, interaction, animation, theme, state)(params); } diff --git a/src/plots/word-cloud/index.ts b/src/plots/word-cloud/index.ts index f828e0db78..aefcec7ab5 100644 --- a/src/plots/word-cloud/index.ts +++ b/src/plots/word-cloud/index.ts @@ -1,7 +1,7 @@ import { deepMix } from '@antv/util'; import { Plot } from '../../core/plot'; import { Adaptor } from '../../core/adaptor'; -import { DataItem, WordCloudOptions } from './types'; +import { Tag, WordCloudOptions } from './types'; import { adaptor } from './adaptor'; import { processImageMask } from './utils'; // 注册的shape @@ -23,7 +23,7 @@ export class WordCloud extends Plot { showTitle: false, showMarkers: false, showCrosshairs: false, - customContent(_, data: { data: DataItem; mappingData: { color: string } }[]) { + customContent(_, data: { data: Tag; mappingData: { color: string } }[]) { if (!data.length) return; // 不完全采用模板字符串,是为了去掉换行符和部分空格, // 便于测试。 diff --git a/src/plots/word-cloud/shapes/word-cloud.ts b/src/plots/word-cloud/shapes/word-cloud.ts index 37538e22b1..6b5d89ec93 100644 --- a/src/plots/word-cloud/shapes/word-cloud.ts +++ b/src/plots/word-cloud/shapes/word-cloud.ts @@ -1,9 +1,9 @@ import { registerShape, Util } from '@antv/g2'; import { ShapeInfo } from '@antv/g2/lib/interface'; import { IGroup, ShapeAttrs } from '@antv/g2/lib/dependents'; -import { DataItem } from '../types'; +import { Tag } from '../types'; -type Config = ShapeInfo & { data: DataItem }; +type Config = ShapeInfo & { data: Tag }; registerShape('point', 'word-cloud', { draw(cfg: Config, group: IGroup) { diff --git a/src/plots/word-cloud/types.ts b/src/plots/word-cloud/types.ts index dd8426726b..08a7568017 100644 --- a/src/plots/word-cloud/types.ts +++ b/src/plots/word-cloud/types.ts @@ -1,16 +1,21 @@ import { ShapeAttrs } from '@antv/g2/lib/dependents'; -import { Options } from '../../types'; +import { Datum, Options } from '../../types'; type FontWeight = ShapeAttrs['fontWeight']; -interface Row { +/** 一个文本信息,wordCloud 内部 */ +export interface Word { /** 文本内容 */ text: string; /** 该文本所占权重 */ value: number; + /** 用于指定颜色字段 */ + color: string | number; + /** 原始数据 */ + datum: Datum; } -export type DataItem = Row & { +export type Tag = Word & { /** 字体 */ font?: string; /** 字体样式 */ @@ -38,16 +43,16 @@ export type DataItem = Row & { /** 词云字体样式 */ interface WordStyle { /** 词云的字体, 当为函数时,其参数是一个经过处理之后的数据元素的值 */ - readonly fontFamily?: string | ((row: Row) => string); + readonly fontFamily?: string | ((word: Word) => string); /** 设置字体的粗细, 当为函数时,其参数是一个经过处理之后的数据元素的值 */ - readonly fontWeight?: FontWeight | ((row: Row) => FontWeight); + readonly fontWeight?: FontWeight | ((word: Word) => FontWeight); /** * 每个单词所占的盒子的内边距,默认为 1。 越大单词之间的间隔越大。 * 当为函数时,其参数是一个经过处理之后的数据元素的值 */ - readonly padding?: number | ((row: Row) => number); + readonly padding?: number | ((word: Word) => number); /** 字体的大小范围,当为函数时,其参数是一个经过处理之后的数据元素的值 */ - readonly fontSize?: [number, number] | ((row: Row) => number); + readonly fontSize?: [number, number] | ((word: Word) => number); /** 旋转的最小角度和最大角度 默认 [0, 90] */ readonly rotation?: [number, number]; /** 旋转实际的步数,越大可能旋转角度越小, 默认是 2 */ diff --git a/src/plots/word-cloud/utils.ts b/src/plots/word-cloud/utils.ts index ddd27fd0ef..afc7fbb7c9 100644 --- a/src/plots/word-cloud/utils.ts +++ b/src/plots/word-cloud/utils.ts @@ -1,17 +1,18 @@ import { Chart, View } from '@antv/g2'; import { isArray, isFunction, isNumber, isString } from '@antv/util'; import { Params } from '../../core/adaptor'; +import { Datum } from '../../types'; import { log, LEVEL, getContainerSize } from '../../utils'; import { wordCloud } from '../../utils/transform/word-cloud'; -import { DataItem, WordCloudOptions } from './types'; +import { Tag, Word, WordCloudOptions } from './types'; /** * 用 DataSet 转换词云图数据 * @param params */ -export function transform(params: Params): DataItem[] { +export function transform(params: Params): Tag[] { const { options } = params; - const { data, imageMask, wordField, weightField, wordStyle, timeInterval } = options; + const { data, imageMask, wordField, weightField, colorField, wordStyle, timeInterval } = options; if (!data || !data.length) { return []; } @@ -19,8 +20,23 @@ export function transform(params: Params): DataItem[] { const arr = data.map((v) => v[weightField]) as number[]; const range = [min(arr), max(arr)] as [number, number]; - return wordCloud(data, { - fields: [wordField, weightField], + // 校验 + if (!isString(wordField) || !isString(weightField)) { + throw new TypeError('Invalid fields: must be an array with 2 strings (e.g. [ "text", "value" ])!'); + } + + // 变换出 text 和 value 字段 + const words = data.map( + (datum: Datum): Word => ({ + text: datum[wordField], + value: datum[weightField], + color: datum[colorField], + datum, // 存一下原始数据 + }) + ); + + // 数据准备在外部做,wordCloud 单纯就是做布局 + return wordCloud(words, { imageMask: imageMask as HTMLImageElement, font: fontFamily, fontSize: getFontSize(options, range), diff --git a/src/utils/transform/word-cloud.ts b/src/utils/transform/word-cloud.ts index dd9ea45b6d..8c3644dab7 100644 --- a/src/utils/transform/word-cloud.ts +++ b/src/utils/transform/word-cloud.ts @@ -1,31 +1,21 @@ -import { deepMix, assign, isString } from '@antv/util'; -import { DataItem } from '../../plots/word-cloud/types'; -import { Data } from '../../types'; +import { isNil, assign } from '@antv/util'; +import { Tag, Word } from '../../plots/word-cloud/types'; type FontWeight = number | 'normal' | 'bold' | 'bolder' | 'lighter'; -interface Row { - /** 文本内容 */ - text: string; - /** 该文本所占权重 */ - value: number; -} - export interface Options { - fields: [string, string]; size: [number, number]; - font?: string | ((row: Row) => string); - fontSize?: number | ((row: Row) => number); - fontWeight?: FontWeight | ((row: Row) => FontWeight); - rotate?: number | ((row: Row) => number); - padding?: number | ((row: Row) => number); + font?: string | ((row: Word) => string); + fontSize?: number | ((row: Word) => number); + fontWeight?: FontWeight | ((row: Word) => FontWeight); + rotate?: number | ((row: Word) => number); + padding?: number | ((row: Word) => number); spiral?: 'archimedean' | 'rectangular' | ((size: [number, number]) => (t: number) => number[]); timeInterval?: number; imageMask?: HTMLImageElement; } const DEFAULT_OPTIONS: Options = { - fields: ['text', 'value'], // fields to keep font: () => 'serif', padding: 1, size: [500, 500], @@ -39,45 +29,47 @@ const DEFAULT_OPTIONS: Options = { * 根据对应的数据对象,计算每个 * 词语在画布中的渲染位置,并返回 * 计算后的数据对象 + * @param words * @param options */ -export function wordCloud(data: Data, options?: Partial) { +export function wordCloud(words: Word[], options?: Partial): Tag[] { // 混入默认配置 options = assign({} as Options, DEFAULT_OPTIONS, options); - return transform(data, options as Options); + return transform(words, options as Options); } -export function transform(data: Data, options: Options) { - // 深拷贝 - data = deepMix([], data); +/** + * 抛出没有混入默认配置的方法,用于测试。 + * @param words + * @param options + */ +export function transform(words: Word[], options: Options) { + // 布局对象 const layout = tagCloud(); - ['font', 'fontSize', 'fontWeight', 'padding', 'rotate', 'size', 'spiral', 'timeInterval'].forEach((key) => { - if (options[key] !== undefined && options[key] !== null) { + ['font', 'fontSize', 'fontWeight', 'padding', 'rotate', 'size', 'spiral', 'timeInterval'].forEach((key: string) => { + if (!isNil(options[key])) { layout[key](options[key]); } }); - const [text, value] = options.fields; - if (!isString(text) || !isString(value)) { - throw new TypeError('Invalid fields: must be an array with 2 strings (e.g. [ "text", "value" ])!'); - } - const words = data.map((row) => ({ - text: row[text], - value: row[value], - })); + layout.words(words); if (options.imageMask) { layout.createMask(options.imageMask); } + const result = layout.start(); const tags: any[] = result._tags; + const bounds = result._bounds || [ { x: 0, y: 0 }, { x: options.size[0], y: options.size[1] }, ]; + tags.forEach((tag) => { tag.x += options.size[0] / 2; tag.y += options.size[1] / 2; }); + const [w, h] = options.size; const hasImage = result.hasImage; tags.push({ @@ -95,7 +87,7 @@ export function transform(data: Data, options: Options) { opacity: 0, }); - return tags as DataItem[]; + return tags; } /* From 4ef598b542f20a136e8a08949b162e96e4912419 Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Thu, 22 Oct 2020 17:33:37 +0800 Subject: [PATCH 8/9] =?UTF-8?q?chore:=20=E8=B0=83=E6=95=B4=E5=8D=95?= =?UTF-8?q?=E4=BE=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/unit/plots/word-cloud/color-spec.ts | 6 +- __tests__/unit/plots/word-cloud/style-spec.ts | 4 +- .../unit/utils/transform/word-cloud-spec.ts | 62 ++++++------------- src/plots/word-cloud/utils.ts | 5 -- 4 files changed, 23 insertions(+), 54 deletions(-) diff --git a/__tests__/unit/plots/word-cloud/color-spec.ts b/__tests__/unit/plots/word-cloud/color-spec.ts index 45100fa2bb..22c1af41cb 100644 --- a/__tests__/unit/plots/word-cloud/color-spec.ts +++ b/__tests__/unit/plots/word-cloud/color-spec.ts @@ -31,7 +31,7 @@ describe('word-cloud color option', () => { cloud.render(); const field = cloud.chart.geometries[0].getGroupFields()[0]; - expect(field).toBe('text'); + expect(field).toBe('color'); }); it('weightField', () => { @@ -47,7 +47,7 @@ describe('word-cloud color option', () => { cloud.render(); const field = cloud.chart.geometries[0].getGroupFields()[0]; - expect(field).toBe('value'); + expect(field).toBe('color'); }); it('x', () => { @@ -63,6 +63,6 @@ describe('word-cloud color option', () => { cloud.render(); const field = cloud.chart.geometries[0].getGroupFields()[0]; - expect(field).toBe('x'); + expect(field).toBe('color'); }); }); diff --git a/__tests__/unit/plots/word-cloud/style-spec.ts b/__tests__/unit/plots/word-cloud/style-spec.ts index f3693b49f3..a3ee5bd556 100644 --- a/__tests__/unit/plots/word-cloud/style-spec.ts +++ b/__tests__/unit/plots/word-cloud/style-spec.ts @@ -1,7 +1,7 @@ import { WordCloud } from '../../../../src'; import { CountryEconomy } from '../../../data/country-economy'; import { createDiv } from '../../../utils/dom'; -import { DataItem } from '../../../../src/plots/word-cloud/types'; +import { Tag } from '../../../../src/plots/word-cloud/types'; describe('word-cloud', () => { it('style', () => { @@ -22,7 +22,7 @@ describe('word-cloud', () => { const { data } = cloud.chart.getOptions(); - data.forEach((item: DataItem) => { + data.forEach((item: Tag) => { // DataSet 处理之后会多出两个无用的数据 if (!item.hasText) return; diff --git a/__tests__/unit/utils/transform/word-cloud-spec.ts b/__tests__/unit/utils/transform/word-cloud-spec.ts index fd0a52a46b..e088e5c347 100644 --- a/__tests__/unit/utils/transform/word-cloud-spec.ts +++ b/__tests__/unit/utils/transform/word-cloud-spec.ts @@ -1,10 +1,8 @@ import DataSet from '@antv/data-set'; -import { DataItem } from '../../../../src/plots/word-cloud/types'; +import { Tag, Word } from '../../../../src/plots/word-cloud/types'; import { processImageMask } from '../../../../src/plots/word-cloud/utils'; import { wordCloud, transform } from '../../../../src/utils/transform/word-cloud'; -type Row = Pick; - const { View } = DataSet; const options = { type: 'tag-cloud', @@ -25,7 +23,7 @@ const data = ['Hello', 'world', 'normally', 'you', 'want', 'more', 'words', 'tha }; }); -function basicCommon(v: DataItem) { +function basicCommon(v: Tag) { expect(v.hasText).toBe(true); expect(typeof v.text).toBe('string'); expect(typeof v.value).toBe('number'); @@ -51,7 +49,7 @@ describe('word-cloud', () => { delete v.x; delete v.y; } - const result1 = wordCloud(data, options as any); + const result1 = wordCloud(data as Word[], options as any); const result2 = dv.rows; result1.forEach(removeXY); @@ -61,32 +59,32 @@ describe('word-cloud', () => { }); it('default', () => { - const result = wordCloud(data); + const result = wordCloud(data as Word[]); basicCommon(result[0]); }); it('callback', () => { - const common = (row: Row) => { + const common = (row: Word) => { expect(typeof row.text).toBe('string'); expect(typeof row.value).toBe('number'); }; - const font = (row: Row) => { + const font = (row: Word) => { common(row); return 'font-test'; }; - const fontWeight = (row: Row): any => { + const fontWeight = (row: Word): any => { common(row); return 'fontWeight-test'; }; - const fontSize = (row: Row) => { + const fontSize = (row: Word) => { common(row); return 11; }; - const rotate = (row: Row) => { + const rotate = (row: Word) => { common(row); return 22; }; - const padding = (row: Row) => { + const padding = (row: Word) => { common(row); return 33; }; @@ -99,7 +97,7 @@ describe('word-cloud', () => { }; }; - const result = wordCloud(data, { + const result = wordCloud(data as Word[], { font, fontWeight, fontSize, @@ -126,51 +124,30 @@ describe('word-cloud', () => { 'data:image/png;base64,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'; const img = await processImageMask(base64); - const result = wordCloud(data, { imageMask: img }); + const result = wordCloud(data as Word[], { imageMask: img }); basicCommon(result[0]); }); it('spiral is rectangular', () => { - const result = wordCloud(data, { spiral: 'rectangular' }); + const result = wordCloud(data as Word[], { spiral: 'rectangular' }); basicCommon(result[0]); }); }); describe('transform', () => { it('default', () => { - const result = transform(data, { - fields: ['text', 'value'], + const result = transform(data as Word[], { size: [800, 800], }); basicCommon(result[0]); }); - it('error of fields', () => { - expect(() => { - transform(data, { - fields: [null, null], - size: [800, 800], - }); - }).toThrow(); - }); - - it('fields is not exit', () => { - const result = transform(data, { - fields: ['a', 'b'], - size: [800, 800], - }); - - expect(result[0].text).toBe(undefined); - expect(result[0].value).toBe(undefined); - }); - it('image mask with size is 0', async () => { const base64 = 'data:image/png;base64,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'; const img = await processImageMask(base64); - const result = transform(data, { - fields: ['text', 'value'], + const result = transform(data as Word[], { size: [0, 0], imageMask: img, }); @@ -181,8 +158,7 @@ describe('transform', () => { }); it('timeInterval is 0', () => { - const result = transform(data, { - fields: ['text', 'value'], + const result = transform(data as Word[], { size: [800, 800], timeInterval: 0, }); @@ -193,8 +169,7 @@ describe('transform', () => { }); it('padding is 0', () => { - const result = transform(data, { - fields: ['text', 'value'], + const result = transform(data as Word[], { size: [800, 800], padding: 0, }); @@ -202,8 +177,7 @@ describe('transform', () => { }); it('rotate is 0', () => { - const result = transform(data, { - fields: ['text', 'value'], + const result = transform(data as Word[], { size: [800, 800], rotate: 0, }); diff --git a/src/plots/word-cloud/utils.ts b/src/plots/word-cloud/utils.ts index afc7fbb7c9..f406af4c84 100644 --- a/src/plots/word-cloud/utils.ts +++ b/src/plots/word-cloud/utils.ts @@ -20,11 +20,6 @@ export function transform(params: Params): Tag[] { const arr = data.map((v) => v[weightField]) as number[]; const range = [min(arr), max(arr)] as [number, number]; - // 校验 - if (!isString(wordField) || !isString(weightField)) { - throw new TypeError('Invalid fields: must be an array with 2 strings (e.g. [ "text", "value" ])!'); - } - // 变换出 text 和 value 字段 const words = data.map( (datum: Datum): Word => ({ From d1aef04bcde1427be425d7d5bf7c7e12e029ae9d Mon Sep 17 00:00:00 2001 From: zhangzhonghe <958414905@qq.com> Date: Thu, 22 Oct 2020 21:06:09 +0800 Subject: [PATCH 9/9] =?UTF-8?q?chore:=20=E4=BC=98=E5=8C=96colorField?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/unit/plots/word-cloud/color-spec.ts | 4 ++-- docs/manual/plots/word-cloud.en.md | 2 +- docs/manual/plots/word-cloud.zh.md | 2 +- examples/word-cloud/basic/API.en.md | 8 ++++++++ examples/word-cloud/basic/API.zh.md | 8 ++++++++ package.json | 2 +- src/plots/word-cloud/adaptor.ts | 4 +--- src/plots/word-cloud/shapes/word-cloud.ts | 2 +- 8 files changed, 23 insertions(+), 9 deletions(-) diff --git a/__tests__/unit/plots/word-cloud/color-spec.ts b/__tests__/unit/plots/word-cloud/color-spec.ts index 22c1af41cb..9a93fa2d7d 100644 --- a/__tests__/unit/plots/word-cloud/color-spec.ts +++ b/__tests__/unit/plots/word-cloud/color-spec.ts @@ -14,8 +14,8 @@ describe('word-cloud color option', () => { cloud.render(); - const field = cloud.chart.geometries[0].getGroupFields()[0]; - expect(field).toBe('text'); + const fields = cloud.chart.geometries[0].getGroupFields(); + expect(fields.length).toBe(1); }); it('wordField', () => { diff --git a/docs/manual/plots/word-cloud.en.md b/docs/manual/plots/word-cloud.en.md index c6d934fcaa..de02d287d5 100644 --- a/docs/manual/plots/word-cloud.en.md +++ b/docs/manual/plots/word-cloud.en.md @@ -43,7 +43,7 @@ order: 0 功能描述: 根据该字段进行颜色映射 -默认配置: wordField 字段的值 +默认配置: 无 #### timeInterval diff --git a/docs/manual/plots/word-cloud.zh.md b/docs/manual/plots/word-cloud.zh.md index 7d7f3820fe..a203db6206 100644 --- a/docs/manual/plots/word-cloud.zh.md +++ b/docs/manual/plots/word-cloud.zh.md @@ -43,7 +43,7 @@ order: 0 功能描述: 根据该字段进行颜色映射 -默认配置: wordField 字段的值 +默认配置: 无 #### timeInterval diff --git a/examples/word-cloud/basic/API.en.md b/examples/word-cloud/basic/API.en.md index 94342e0924..08b0fa1a56 100644 --- a/examples/word-cloud/basic/API.en.md +++ b/examples/word-cloud/basic/API.en.md @@ -32,6 +32,14 @@ 默认配置: 无 +#### colorField + +**可选**, _string_ + +功能描述: 根据该字段进行颜色映射 + +默认配置: 无 + #### timeInterval **可选**, _number_ diff --git a/examples/word-cloud/basic/API.zh.md b/examples/word-cloud/basic/API.zh.md index c3cf0d0d20..593cf960d1 100644 --- a/examples/word-cloud/basic/API.zh.md +++ b/examples/word-cloud/basic/API.zh.md @@ -32,6 +32,14 @@ 默认配置: 无 +#### colorField + +**可选**, _string_ + +功能描述: 根据该字段进行颜色映射 + +默认配置: 无 + #### timeInterval **可选**, _number_ diff --git a/package.json b/package.json index 49817888ed..6a38fa5985 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ }, "dependencies": { "@antv/event-emitter": "^0.1.2", - "@antv/g2": "^4.1.0-beta.13", + "@antv/g2": "^4.1.0-beta.14", "d3-hierarchy": "^2.0.0", "dayjs": "^1.8.36", "size-sensor": "^1.0.1", diff --git a/src/plots/word-cloud/adaptor.ts b/src/plots/word-cloud/adaptor.ts index be3b23b835..66550f8305 100644 --- a/src/plots/word-cloud/adaptor.ts +++ b/src/plots/word-cloud/adaptor.ts @@ -21,9 +21,7 @@ function geometry(params: Params): Params { options: { xField: 'x', yField: 'y', - // 给 seriesField 一个默认值,否则它为空时 - // 每个词语的颜色会显示成白色。 - seriesField: colorField ? 'color' : 'text', + seriesField: colorField && 'color', point: { color, shape: 'word-cloud', diff --git a/src/plots/word-cloud/shapes/word-cloud.ts b/src/plots/word-cloud/shapes/word-cloud.ts index 6b5d89ec93..8e75109fc0 100644 --- a/src/plots/word-cloud/shapes/word-cloud.ts +++ b/src/plots/word-cloud/shapes/word-cloud.ts @@ -33,7 +33,7 @@ function getTextAttrs(cfg: Config): ShapeAttrs { textAlign: 'center', fontFamily: cfg.data.font, fontWeight: cfg.data.weight, - fill: cfg.color, + fill: cfg.color || cfg.defaultStyle.stroke, textBaseline: 'alphabetic', }; }