Skip to content

Commit

Permalink
fix(word-cloud): fix tooltip and add demo of custom tooltip
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangzhonghe committed Oct 21, 2020
1 parent d8dd66c commit 98011e5
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 30 deletions.
32 changes: 32 additions & 0 deletions examples/word-cloud/basic/demo/custom-tooltip.ts
Original file line number Diff line number Diff line change
@@ -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 `<h4 style="margin-top: 1em;">title</h4>
<li class="g2-tooltip-list-item" style="margin-bottom:4px;display:flex;align-items:center;">
<span style="background-color:${data[0]?.mappingData?.color};" class="g2-tooltip-marker"></span>
<span style="display:inline-flex;flex:1;justify-content:space-between">
<span style="margin-right: 16px;">${data[0]?.data.text}:</span><span>${data[0]?.data.value}</span>
</span>
</li>`;
},
},
});

wordCloud.render();
});
8 changes: 8 additions & 0 deletions examples/word-cloud/basic/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
}
2 changes: 1 addition & 1 deletion src/plots/word-cloud/adaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function geometry(params: Params<WordCloudOptions>): Params<WordCloudOptions> {
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;
}
Expand Down
11 changes: 10 additions & 1 deletion src/plots/word-cloud/index.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -23,6 +23,15 @@ export class WordCloud extends Plot<WordCloudOptions> {
showTitle: false,
showMarkers: false,
showCrosshairs: false,
customContent(_, data: { data: DataItem; mappingData: any }[]) {
if (!data.length) return;
return `<li class="g2-tooltip-list-item" style="margin-bottom:4px;display:flex;align-items:center;">
<span style="background-color:${data[0]?.mappingData?.color};" class="g2-tooltip-marker"></span>
<span style="display:inline-flex;flex:1;justify-content:space-between">
<span style="margin-right: 16px;">${data[0]?.data.text}:</span><span>${data[0]?.data.value}</span>
</span>
</li>`;
},
},
wordStyle: {
fontFamily: 'Verdana',
Expand Down
4 changes: 2 additions & 2 deletions src/plots/word-cloud/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export type DataItem = Row & {
/** 单词所占盒子的高度 */
height?: number;
/** x 轴坐标 */
x?: number;
_x?: number;
/** y 轴坐标 */
y?: number;
_y?: number;
};

/** 词云字体样式 */
Expand Down
53 changes: 27 additions & 26 deletions src/utils/transform/word-cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});

Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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++) {
Expand Down

0 comments on commit 98011e5

Please sign in to comment.