import React, { Component } from 'react'; import { Chart, Geom, Coord, Shape, Tooltip } from 'bizcharts'; import DataSet from '@antv/data-set'; import debounce from 'lodash/debounce'; import classNames from 'classnames'; import autoHeight from '../autoHeight'; import styles from './index.less'; const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png'; interface TagCloudProps { data: Array<{ name: string; value: number; }>; height: number; style?: React.CSSProperties; className: string; } interface TagCloudState { dv: any; w: number; h: number; } class TagCloud extends Component { state = { dv: null, w: 0, h: 0, }; root: HTMLDivElement; requestRef: number; isUnmount: boolean; imageMask: HTMLImageElement; componentDidMount() { requestAnimationFrame(() => { this.initTagCloud(); this.renderChart(); }); window.addEventListener('resize', this.resize, { passive: true }); } componentDidUpdate(preProps) { const { data } = this.props; if (JSON.stringify(preProps.data) !== JSON.stringify(data)) { this.renderChart(this.props); } } componentWillUnmount() { this.isUnmount = true; window.cancelAnimationFrame(this.requestRef); window.removeEventListener('resize', this.resize); } resize = () => { this.requestRef = requestAnimationFrame(() => { this.renderChart(); }); }; saveRootRef = node => { this.root = node; }; initTagCloud = () => { function getTextAttrs(cfg) { return Object.assign({}, cfg.style, { fillOpacity: cfg.opacity, fontSize: cfg.origin._origin.size, rotate: cfg.origin._origin.rotate, text: cfg.origin._origin.text, textAlign: 'center', fontFamily: cfg.origin._origin.font, fill: cfg.color, textBaseline: 'Alphabetic', }); } // 给point注册一个词云的shape Shape.registerShape('point', 'cloud', { drawShape(cfg, container) { // todo:这里还不知道怎么改 const attrs = getTextAttrs(cfg); return container.addShape('text', { attrs: Object.assign(attrs, { x: cfg.x, y: cfg.y, }), }); }, }); }; renderChart = debounce((nextProps?: TagCloudProps) => { // const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C']; const { data, height } = nextProps || this.props; if (data.length < 1 || !this.root) { return; } const h = height; const w = this.root.offsetWidth; const onload = () => { const dv = new DataSet.View().source(data); const range = dv.range('value'); const [min, max] = range; dv.transform({ type: 'tag-cloud', fields: ['name', 'value'], imageMask: this.imageMask, font: 'Verdana', size: [w, h], // 宽高设置最好根据 imageMask 做调整 padding: 0, timeInterval: 5000, // max execute time rotate() { return 0; }, fontSize(d) { // eslint-disable-next-line return Math.pow((d.value - min) / (max - min), 2) * (17.5 - 5) + 5; }, }); if (this.isUnmount) { return; } this.setState({ dv, w, h, }); }; if (!this.imageMask) { this.imageMask = new Image(); this.imageMask.crossOrigin = ''; this.imageMask.src = imgUrl; this.imageMask.onload = onload; } else { onload(); } }, 500); render() { const { className, height } = this.props; const { dv, w, h } = this.state; return (
{dv && ( )}
); } } export default autoHeight()(TagCloud);