diff --git a/__tests__/bugs/issue-1754-spec.ts b/__tests__/bugs/issue-1754-spec.ts
new file mode 100644
index 0000000000..90b887a2cc
--- /dev/null
+++ 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/__tests__/unit/plots/word-cloud/color-spec.ts b/__tests__/unit/plots/word-cloud/color-spec.ts
new file mode 100644
index 0000000000..9a93fa2d7d
--- /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 fields = cloud.chart.geometries[0].getGroupFields();
+ expect(fields.length).toBe(1);
+ });
+
+ 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('color');
+ });
+
+ 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('color');
+ });
+
+ 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('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 ee0955a2df..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',
@@ -22,11 +20,10 @@ const data = ['Hello', 'world', 'normally', 'you', 'want', 'more', 'words', 'tha
return {
text: d,
value: 5 + Math.random() * 10,
- test: 'haha',
};
});
-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');
@@ -52,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);
@@ -62,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;
};
@@ -100,7 +97,7 @@ describe('word-cloud', () => {
};
};
- const result = wordCloud(data, {
+ const result = wordCloud(data as Word[], {
font,
fontWeight,
fontSize,
@@ -127,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,
});
@@ -182,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,
});
@@ -194,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,
});
@@ -203,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/docs/manual/plots/word-cloud.en.md b/docs/manual/plots/word-cloud.en.md
index d9b57fec0f..de02d287d5 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_
+
+功能描述: 根据该字段进行颜色映射
+
+默认配置: 无
+
#### timeInterval
**可选**, _number_
diff --git a/docs/manual/plots/word-cloud.zh.md b/docs/manual/plots/word-cloud.zh.md
index f0fa71ae32..a203db6206 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_
+
+功能描述: 根据该字段进行颜色映射
+
+默认配置: 无
+
#### timeInterval
**可选**, _number_
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/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/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..bbd91014b6 100644
--- a/examples/word-cloud/basic/demo/meta.json
+++ b/examples/word-cloud/basic/demo/meta.json
@@ -35,6 +35,22 @@
"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"
+ },
+ {
+ "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/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 1879716531..66550f8305 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,25 +11,30 @@ 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 { wordField, color } = options;
- const geometry = findGeometry(chart, 'point');
+ const p = deepMix({}, params, {
+ options: {
+ xField: 'x',
+ yField: 'y',
+ seriesField: colorField && 'color',
+ point: {
+ color,
+ shape: 'word-cloud',
+ },
+ },
+ });
+
+ const { ext } = point(p);
+ ext.geometry.label(false);
- geometry.color(wordField, color);
+ chart.coordinate().reflect('y');
+ chart.axis(false);
+ chart.legend(false);
return params;
}
@@ -45,58 +52,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
@@ -104,5 +59,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 a5bacdcb27..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 { WordCloudOptions } from './types';
+import { Tag, WordCloudOptions } from './types';
import { adaptor } from './adaptor';
import { processImageMask } from './utils';
// 注册的shape
@@ -23,6 +23,19 @@ export class WordCloud extends Plot {
showTitle: false,
showMarkers: false,
showCrosshairs: false,
+ customContent(_, data: { data: Tag; mappingData: { color: string } }[]) {
+ if (!data.length) return;
+ // 不完全采用模板字符串,是为了去掉换行符和部分空格,
+ // 便于测试。
+ return (
+ '' +
+ `` +
+ '' +
+ `${data[0]?.data.text}:${data[0]?.data.value}` +
+ '' +
+ ''
+ );
+ },
},
wordStyle: {
fontFamily: 'Verdana',
@@ -73,8 +86,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..8e75109fc0 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) {
@@ -28,14 +28,12 @@ registerShape('point', 'word-cloud', {
function getTextAttrs(cfg: Config): ShapeAttrs {
return {
- ...cfg.defaultStyle,
- ...cfg.style,
fontSize: cfg.data.size,
text: cfg.data.text,
textAlign: 'center',
fontFamily: cfg.data.font,
fontWeight: cfg.data.weight,
- fill: cfg.color,
+ fill: cfg.color || cfg.defaultStyle.stroke,
textBaseline: 'alphabetic',
};
}
diff --git a/src/plots/word-cloud/types.ts b/src/plots/word-cloud/types.ts
index 721a85a1ff..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 */
@@ -61,6 +66,8 @@ export interface WordCloudOptions extends Options {
readonly wordField: string;
/** 词条权重字段 */
readonly weightField: string;
+ /** 根据该字段进行颜色映射 */
+ readonly colorField?: string;
/** 遮罩图片实例,可以是图片 URL 或者 base64 */
readonly imageMask?: HTMLImageElement | string;
/** 最大执行时间 */
diff --git a/src/plots/word-cloud/utils.ts b/src/plots/word-cloud/utils.ts
index ddd27fd0ef..f406af4c84 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,18 @@ 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],
+ // 变换出 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 e755c85147..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,46 +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) => {
- row.text = row[text];
- row.value = row[value];
- return row;
- });
+
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({
@@ -96,7 +87,7 @@ export function transform(data: Data, options: Options) {
opacity: 0,
});
- return tags as DataItem[];
+ return tags;
}
/*