antv/g2 图表的动态加载、legend(图例)的自定义显示以及解决x轴最右侧刻度值显示不全的问题

14,363 阅读3分钟

动态加载的实现

  1. constructor() 中定义组件全局变量 this.chart

    constructor(props) {
        super(props);
        this.state = {}
        
        this.chart = {};
    }
    

    这样就可以在该组件全局而不仅仅是某个方法内部使用了。

  2. 初始化图表

    draw = (list) => {
        this.chart = new G2.Chart({
            container: 'chart',
            forceFit: true,
            height: 500,
            padding: 70
        });
        this.chart.source(list, {
            ref_date: {
                range: [0,1]
            }
        });
        this.chart.tooltip({
            crosshairs: {
                type: 'line'
            }
        });
                    ...
                    ...
                    ...
        this.chart.line().position('ref_date*value').color('name');
        this.chart.render();
    }
    

    这样就定义好了图表参数。

    该方法只会执行一次,如果多次执行就会生成多个图表,这样就需要用到另一种比较复杂的方法来操作了,因为要使用到节点。

  3. 动态加载

    g2的动态加载就依赖与一个方法:chart.changeData(list) 在此就能意识到将chart写入全局的意义了,数据(list)的发生变化,changeData方法必然不能够在 draw() 方法中执行,因为那样会多生成一个图表,既然如此,还不如直接选择通过dom操作,每次数据更新删除旧节点了,通过chart.render()方法就可以了,也就没必要使用changeData()方法了,所以要想使用changeData方法就需要能在其它方法中使用chart,所以将chart定义在全局是很必要的。

    接下来就很简单了,每次数据改变setState的时候,回调里面调用一下该方法就行了。

    handleRadio = (e) => {
        this.setState({
            type: e.target.value
        },() => {
            this.chart.changeData(newList);
        })
    }
    

图例的自定义显示

比如要实现图示中表单样式的图例:

表格样式为:

menu name name
一级菜单 用户中心 违规查询
二级菜单 用户中心-我要充值/用户中心-个人中心 违规查询-违规查询/违规查询-罚单代缴

要实现这样的legend样式,只能拼字符串了,官方文档也有说明: 图例html实现

修改this.chart.legend 属性

this.chart.legend({
            useHtml: true,
            hoverable: true,
            containerTpl: '<div class="g2-legend"><table class="g2-legend-list"></table></div>',
            itemTpl: (value, color, checked, index) => {
                checked = checked ? 'checked' : 'unChecked';

                const { priArr, secArr, priNum, secNum } = this.priSecArr;
                priArr.forEach(item => {
                    ...
                    数据处理
                    ...
                })
                secArr.forEach(item => {
                    ...
                    数据处理
                    ...
                })
                if(index === priNum + secNum - 1) {
                    let str_pri = '', str_sec = ''; //  两个 tr标签
                    // 这里面用到的类名都是g2规定好的,不能乱设置
                    priArr.forEach(item => {
                        var markerDom = '<div class="g2-legend-marker" style="display:inline-block;background-color:' + item.color + ';width:9px;height:9px;border-radius:50%;margin-right:4px;vertical-align:baseline"></div>';
                        var nameDom = '<div class="legend-item-name" style="display:inline-block">' + item.value + '</div>';
                        str_pri += '<td style="padding: 0 15px;text-align: left" class="g2-legend-list-item item-' + item.index + ' ' + item.checked + '" data-value="' + item.value + '" data-color="' + item.color +'">' + markerDom + nameDom + '</td>'
                    })
                    secArr.forEach(item => {
                        str_sec += '<td style="vertical-align:top;padding:9px 0;text-align:left">'
                        if(item.length > 0) {
                            item.forEach(i => {
                                var markerDom = '<div class="g2-legend-marker" style="display:inline-block;background-color:' + i.color + ';width:9px;height:9px;border-radius:50%;margin-right:4px;vertical-align:baseline"></div>';
                                var nameDom = '<div class="legend-item-name" style="display:inline-block">' + i.value + '</div>';
                                str_sec += '<div style="padding:0 15px" class="g2-legend-list-item item-' + i.index + ' ' + i.checked + '" data-value="' + i.value + '" data-color="' + i.color +'">' + markerDom + nameDom + '</div>'
                            })
                        }
                        str_sec += '</td>';
                    })
                    str_pri = '<tr><td>一级菜单</td>' + str_pri + '</tr>';
                    str_sec = '<tr><td style="vertical-align:top;padding:9px 0;">二级菜单</td>' + str_sec + '</tr>';
                    return '<tbody class="g2-legend-list-item item-0">' + str_pri + str_sec + '</tbody>' 
                } else {
                    return '<td></td>'
                }
            },
            'g2-legend': {
                position: 'unset!important',
                display: 'flex',
                justifyContent: 'center'
            }
        })

反正去试一下就知道怎么玩了。

X轴最右侧刻度值显示不全

如图:

就是这么个情况,要解决也非常简单,给chart添加一个padding就好了

this.chart = new G2.chart({
    container: 'chart',
    forceFit: true,
    height: 500
    
    padding: 70 //就是这里
})

这样就完事儿了。