123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- import React, { PureComponent } from 'react';
- import classNames from 'classnames';
- import G2 from 'g2';
- import Cloud from 'g-cloud';
- import Debounce from 'lodash-decorators/debounce';
- import Bind from 'lodash-decorators/bind';
- import styles from './index.less';
- /* eslint no-underscore-dangle: 0 */
- /* eslint no-param-reassign: 0 */
- const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png';
- class TagCloud extends PureComponent {
- componentDidMount() {
- this.initTagCloud();
- this.renderChart();
- window.addEventListener('resize', this.resize);
- }
- componentWillReceiveProps(nextProps) {
- if (this.props.data !== nextProps.data) {
- this.renderChart(nextProps.data);
- }
- }
- componentWillUnmount() {
- window.removeEventListener('resize', this.resize);
- this.renderChart.cancel();
- }
- resize = () => {
- this.renderChart();
- }
- initTagCloud = () => {
- const { Util, Shape } = G2;
- function getTextAttrs(cfg) {
- const textAttrs = Util.mix(true, {}, {
- fillOpacity: cfg.opacity,
- fontSize: cfg.size,
- rotate: cfg.origin._origin.rotate,
- // rotate: cfg.origin._origin.rotate,
- text: cfg.origin._origin.text,
- textAlign: 'center',
- fill: cfg.color,
- textBaseline: 'Alphabetic',
- }, cfg.style);
- return textAttrs;
- }
- // 给point注册一个词云的shape
- Shape.registShape('point', 'cloud', {
- drawShape(cfg, container) {
- cfg.points = this.parsePoints(cfg.points);
- const attrs = getTextAttrs(cfg);
- const shape = container.addShape('text', {
- attrs: Util.mix(attrs, {
- x: cfg.points[0].x,
- y: cfg.points[0].y,
- }),
- });
- return shape;
- },
- });
- }
- saveRootRef = (node) => {
- this.root = node;
- }
- saveNodeRef = (node) => {
- this.node = node;
- }
- @Bind()
- @Debounce(500)
- renderChart(newData) {
- const data = newData || this.props.data;
- if (!data || data.length < 1) {
- return;
- }
- const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
- const height = this.props.height * 4;
- let width = 0;
- if (this.root) {
- width = this.root.offsetWidth * 4;
- }
- data.sort((a, b) => b.value - a.value);
- const max = data[0].value;
- const min = data[data.length - 1].value;
- // 构造一个词云布局对象
- const layout = new Cloud({
- words: data,
- width,
- height,
- rotate: () => 0,
- // 设定文字大小配置函数(默认为12-24px的随机大小)
- size: words => (((words.value - min) / (max - min)) * 50) + 30,
- // 设定文字内容
- text: words => words.name,
- });
- layout.image(imgUrl, (imageCloud) => {
- // clean
- if (this.node) {
- this.node.innerHTML = '';
- }
- // 执行词云布局函数,并在回调函数中调用G2对结果进行绘制
- imageCloud.exec((texts) => {
- const chart = new G2.Chart({
- container: this.node,
- width,
- height,
- plotCfg: {
- margin: 0,
- },
- });
- chart.legend(false);
- chart.axis(false);
- chart.tooltip(false);
- chart.source(texts);
- // 将词云坐标系调整为G2的坐标系
- chart.coord().reflect();
- chart
- .point()
- .position('x*y')
- .color('text', colors)
- .size('size', size => size)
- .shape('cloud')
- .style({
- fontStyle: texts[0].style,
- fontFamily: texts[0].font,
- fontWeight: texts[0].weight,
- });
- chart.render();
- });
- });
- }
- render() {
- return (
- <div
- className={classNames(styles.tagCloud, this.props.className)}
- ref={this.saveRootRef}
- style={{ width: '100%' }}
- >
- <div ref={this.saveNodeRef} style={{ height: this.props.height }} />
- </div>
- );
- }
- }
- export default TagCloud;
|