Skip to content

Commit 7450ab0

Browse files
committed
feat(word-cloud): add customPlacement opiton
1 parent d5a14cc commit 7450ab0

File tree

3 files changed

+62
-31
lines changed

3 files changed

+62
-31
lines changed

src/plots/word-cloud/types.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,23 @@ export type Tag = Word & {
4242
/** 词云字体样式 */
4343
interface WordStyle {
4444
/** 词云的字体, 当为函数时,其参数是一个经过处理之后的数据元素的值 */
45-
readonly fontFamily?: string | ((word: Word) => string);
45+
readonly fontFamily?: string | ((word: Word, index?: number, words?: Word[]) => string);
4646
/** 设置字体的粗细, 当为函数时,其参数是一个经过处理之后的数据元素的值 */
47-
readonly fontWeight?: FontWeight | ((word: Word) => FontWeight);
47+
readonly fontWeight?: FontWeight | ((word: Word, index?: number, words?: Word[]) => FontWeight);
4848
/**
4949
* 每个单词所占的盒子的内边距,默认为 1。 越大单词之间的间隔越大。
5050
* 当为函数时,其参数是一个经过处理之后的数据元素的值
5151
*/
52-
readonly padding?: number | ((word: Word) => number);
52+
readonly padding?: number | ((word: Word, index?: number, words?: Word[]) => number);
5353
/** 字体的大小范围,当为函数时,其参数是一个经过处理之后的数据元素的值 */
54-
readonly fontSize?: [number, number] | ((word: Word) => number);
54+
readonly fontSize?: [number, number] | ((word: Word, index?: number, words?: Word[]) => number);
5555
/**
5656
* 旋转的最小角度和最大角度 默认 [0, 90]。
5757
*
5858
* 注意:如果值是 number 或者 function ,则
5959
* `rotationSteps` 选项将失效。
6060
*/
61-
readonly rotation?: [number, number] | number | ((word: Word) => number);
61+
readonly rotation?: [number, number] | number | ((word: Word, index?: number, words?: Word[]) => number);
6262
/**
6363
* 旋转实际的步数,越大可能旋转角度越小, 默认是 2。
6464
*
@@ -93,6 +93,10 @@ export interface WordCloudOptions extends Options {
9393
* 默认是 `archimedean`。
9494
*/
9595
readonly spiral?: 'archimedean' | 'rectangular';
96-
/** 文字样式配置 */
96+
/**
97+
* 自定义每个词语的坐标。
98+
* 注意:使用该选项时,应配合 `wordStyle` 中的其它选项同时使用。
99+
*/
100+
readonly customPlacement?: (word: Word, index?: number, words?: Word[]) => { x: number; y: number };
97101
readonly wordStyle?: WordStyle;
98102
}

src/plots/word-cloud/utils.ts

+35-8
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,27 @@ import { isArray, isFunction, isNumber, isString } from '@antv/util';
33
import { Params } from '../../core/adaptor';
44
import { Datum } from '../../types';
55
import { log, LEVEL, getContainerSize } from '../../utils';
6-
import { wordCloud } from '../../utils/transform/word-cloud';
6+
import { functor, wordCloud } from '../../utils/transform/word-cloud';
77
import { Tag, Word, WordCloudOptions } from './types';
88

99
/**
1010
* 用 DataSet 转换词云图数据
1111
* @param params
1212
*/
1313
export function transform(params: Params<WordCloudOptions>): Tag[] {
14-
const { options } = params;
15-
const { data, imageMask, wordField, weightField, colorField, wordStyle, timeInterval, random, spiral } = options;
14+
const { options: rawOptions } = params;
15+
const {
16+
data,
17+
imageMask,
18+
wordField,
19+
weightField,
20+
colorField,
21+
wordStyle,
22+
timeInterval,
23+
random,
24+
spiral,
25+
customPlacement,
26+
} = rawOptions;
1627
if (!data || !data.length) {
1728
return [];
1829
}
@@ -30,20 +41,36 @@ export function transform(params: Params<WordCloudOptions>): Tag[] {
3041
})
3142
);
3243

33-
// 数据准备在外部做,wordCloud 单纯就是做布局
34-
return wordCloud(words, {
44+
const options = {
3545
imageMask: imageMask as HTMLImageElement,
3646
font: fontFamily,
37-
fontSize: getFontSize(options, range),
47+
fontSize: getFontSize(rawOptions, range),
3848
fontWeight: fontWeight,
3949
// 图表宽高减去 padding 之后的宽高
4050
size: getSize(params as any),
4151
padding: padding,
4252
timeInterval,
4353
random,
4454
spiral,
45-
rotate: getRotate(options),
46-
});
55+
rotate: getRotate(rawOptions),
56+
};
57+
58+
// 自定义布局函数
59+
if (isFunction(customPlacement)) {
60+
return words.map((word: Word, index: number, words: Word[]) => ({
61+
hasText: !!word.text,
62+
font: functor(options.font)(word, index, words),
63+
weight: functor(options.fontWeight)(word, index, words),
64+
rotate: functor(options.rotate)(word, index, words),
65+
size: functor(options.fontSize)(word, index, words),
66+
style: 'normal',
67+
...word,
68+
...customPlacement(word, index, words),
69+
}));
70+
}
71+
72+
// 数据准备在外部做,wordCloud 单纯就是做布局
73+
return wordCloud(words, options);
4774
}
4875

4976
/**

src/utils/transform/word-cloud.ts

+17-17
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { isNil, assign } from '@antv/util';
1+
import { isNil, isFunction, assign } from '@antv/util';
22
import { Tag, Word } from '../../plots/word-cloud/types';
33

44
type FontWeight = number | 'normal' | 'bold' | 'bolder' | 'lighter';
55

66
export interface Options {
77
size: [number, number];
8-
font?: string | ((row: Word) => string);
9-
fontSize?: number | ((row: Word) => number);
10-
fontWeight?: FontWeight | ((row: Word) => FontWeight);
11-
rotate?: number | ((row: Word) => number);
12-
padding?: number | ((row: Word) => number);
8+
font?: string | ((row: Word, index?: number, words?: Word[]) => string);
9+
fontSize?: number | ((row: Word, index?: number, words?: Word[]) => number);
10+
fontWeight?: FontWeight | ((row: Word, index?: number, words?: Word[]) => FontWeight);
11+
rotate?: number | ((row: Word, index?: number, words?: Word[]) => number);
12+
padding?: number | ((row: Word, index?: number, words?: Word[]) => number);
1313
spiral?: 'archimedean' | 'rectangular' | ((size: [number, number]) => (t: number) => number[]);
1414
random?: number | (() => number);
1515
timeInterval?: number;
@@ -305,8 +305,8 @@ function cloudCanvas() {
305305
return document.createElement('canvas');
306306
}
307307

308-
function functor(d) {
309-
return typeof d === 'function'
308+
export function functor(d) {
309+
return isFunction(d)
310310
? d
311311
: function () {
312312
return d;
@@ -327,7 +327,7 @@ function tagCloud() {
327327
padding = cloudPadding,
328328
spiral = archimedeanSpiral,
329329
random = Math.random,
330-
words: any = [],
330+
words = [],
331331
timeInterval = Infinity;
332332

333333
const text = cloudText;
@@ -342,14 +342,14 @@ function tagCloud() {
342342
n = words.length,
343343
tags = [],
344344
data = words
345-
.map(function (d, i) {
346-
d.text = text.call(this, d, i);
347-
d.font = font.call(this, d, i);
348-
d.style = fontStyle.call(this, d, i);
349-
d.weight = fontWeight.call(this, d, i);
350-
d.rotate = rotate.call(this, d, i);
351-
d.size = ~~fontSize.call(this, d, i);
352-
d.padding = padding.call(this, d, i);
345+
.map(function (d, i, data) {
346+
d.text = text.call(this, d, i, data);
347+
d.font = font.call(this, d, i, data);
348+
d.style = fontStyle.call(this, d, i, data);
349+
d.weight = fontWeight.call(this, d, i, data);
350+
d.rotate = rotate.call(this, d, i, data);
351+
d.size = ~~fontSize.call(this, d, i, data);
352+
d.padding = padding.call(this, d, i, data);
353353
return d;
354354
})
355355
.sort(function (a, b) {

0 commit comments

Comments
 (0)