Echarts 小技巧

警告
本文最后更新于 2023-10-22,文中内容可能已过时。

Echarts 小技巧

  • option 中常用的配置就是 title tooltip legend 数据相关:series 等

  • radar 的不同模式中 的 legend.data 中,对数组成员要求程度不一样,有的时候要求必须是字符串,所以保险一点,任何时候都使用字符串

  • 保险一点:任何 name 属性都是用字符串,legend.data 中都是用字符串

  • x 轴和 y 轴都可以设置 position(坐标轴的位置,左右或者上下)和 inverse(是否反向,设置坐标轴起点的方向)属性,通过两个熟悉配合可以随意设置坐标轴的位置

  • 做横向柱状图的时候,

    1
    2
    3
    4
    5
    6
    7
    
    yAxis: {
        type: 'category',
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    xAxis: {
        type: 'value'
    },

    类别类下一定要有类别的 data

  • 关系图显示特定的路径

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    
    this.showPath = function(path){
        // 获取 echarts 对象
        var graphObject = compsContainer['UID_73bd1bf73e5985929713d24c7bcbedcd'].chart;
        // 获取对象的 option
        var graphOption = graphObject.getOption();
    
        graphOption.series[0].lineStyle.opacity = 0.06
        graphOption.series[0].itemStyle.opacity = 0.06
        // path 变量中保存的是所有通过的部分节点
        var arr = this.path.split(",");
        for (var index = 1; index < arr.length; index++) {
            var preNode = arr[index-1];
            var nowNode = arr[index];
            var relationship =null;
            $.each( this.pageData.relationships, function(i, n){
                if((n.startId == preNode && n.endId == nowNode) || (n.endId == preNode && n.startId == nowNode)){
                    relationship = n;
                    return false;
                } 
            });
            // relationship.startId  endId  id
            graphOption.series[0].data.forEach((item) => {
                // 核心代码,直接修改 option 中的 data 中的节点的属性,设置透明度,首先突出某个节点和隐藏某个节点的效果
                // 已经设置过了的节点不再设置,避免遍历后面的节点的时候覆盖前面设置的节点的属性
                if(!item.itemStyle.hasSet || item.itemStyle.hasSet == 0){
                    if(item.name== relationship.startId ||item.name== relationship.endId ||item.name== relationship.id ){
                        item.itemStyle.opacity = 1
                        item.itemStyle.hasSet = 1
                    }else{
                        item.itemStyle.opacity = 0.06
                    }
                }
            })
            graphOption.series[0].links.forEach((item) => {
                // 关系也是如此
                // 不过这里有一个 bug,关系设置透明度之后,关系上的文字的透明度并不是同步修改的,所以这里额外把文字颜色也改了
                if(!item.lineStyle.hasSet || item.lineStyle.hasSet == 0){
                    if( (item.source == relationship.startId && item.target == relationship.id) || 
                        (item.target == relationship.startId && item.source == relationship.id) || 
                        (item.source == relationship.endId && item.target == relationship.id) || 
                        (item.target == relationship.endId && item.source == relationship.id)){
                        item.lineStyle.opacity = 1
                        item.lineStyle.color = item.lineStyle.colorBack
                        item.emphasis.lineStyle.opacity = 1
                        item.lineStyle.hasSet = 1
                    }else{
                        item.lineStyle.color = 'none'
                        item.lineStyle.opacity = 0.06
                        item.emphasis.lineStyle.opacity = 0.06
    
                    }
                }
            })
        }
        // 核心代码,刷新 echarts 图
        graphObject.setOption(graphOption);
    }
    
    this.hidePath = function(){
        graphObject = compsContainer['UID_73bd1bf73e5985929713d24c7bcbedcd'].chart;
        graphOption = graphObject.getOption();
    
        // 重置透明度和颜色
        graphOption.series[0].data.forEach((item) => {
            item.itemStyle.opacity = 1
            item.itemStyle.hasSet = 0
        })
        graphOption.series[0].links.forEach((item) => {
            item.lineStyle.opacity = 1
            item.emphasis.lineStyle.opacity = 1
            item.lineStyle.color = item.lineStyle.colorBack
            item.lineStyle.hasSet = 0
        })
        // 刷新 echarts 图
        graphObject.setOption(graphOption);
    }
  • 关系图 graph 注意 节点的 name 属性和 links 的 source 和 target 属性最好是字符串,而不是数字,不然有一定概率 link 会失效, 可以在 name 的两头强制添加 “’” 来转化为字符串。

  • 鼠标点击事件的监听:事件与行为 - 概念篇 - Handbook - Apache ECharts

    1
    2
    3
    4
    
    myChart.on('click', function(params) {
      // 控制台打印数据的名称
      console.log(params.name);
    });
  • echarts 的 effectscatter 类型的 series 的 data 在更新数据的时候,只有前两个才能实现平滑动效。后面的都是闪现的效果 因此,我们最好两数据一个 data,一个 series

  • 所有的配置颜色的地方,都可以通过以下配置配置成渐变色

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    color: {
        x: 0,
        y: 1,
        x2: 0,
        y2: 0,
        colorStops: [{
            offset: 0, color: 'red' // 0% 处的颜色
        }, {
            offset: 1, color: 'blue' // 100% 处的颜色
        }],
        global: false // 缺省为 false
    }

    方向上是 从左到右是 x->x2 从上到下是 y->y2

  • echarts 想要实现数据切换后,图形的顺滑变化,只能使用 echartsInstance.setOption(),Documentation - Apache ECharts

    1
    2
    3
    
    chart.setOption(option, {
        replaceMerge: ['series']
    });

    最常用的场景是,我们更新了某个 series 的 data,希望图形可以平滑过渡,此时,我们在 option 中设置好新的所有的 option,然后调用下面的语句仅更新 chart 对象的所有 series。 注意,每个 series 都要设置好唯一的 id,旧的 series 会根据 id 匹配新的 series,进行合并,删除,和创建

    此时使用的是 替换合并 模式

  • 参考博客:https://segmentfault.com/q/1010000016518635 树组件在加载的时候手动控制特定节点的展开与收起, data 为 type 为 ’tree’的 series 的 data 属性 manuallyExpandDeptId 手动维护的展开节点的 id,在这个数组中的就展开,不在的就折叠

    参考源文件-deptTree.html

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    
    // 方法
    , setDefaultExpandDeptId: function (node, depth) {
        // 顶级节点就是第一层
        var that = this;
        // initialExpandDepth 为默认展开到第几层
        if (depth <= this.initialExpandDepth) {
            that.manuallyExpandDeptId.push(node.deptId);
            if (node.children) {
                for (var childNodeIndex in node.children) {
                    that.setDefaultExpandDeptId(node.children[childNodeIndex], depth + 1);
                }
            }
        }
        return node;
    }
    , syncExpandNode: function (nodes) {
        var that = this;
        // 控制节点的展开与收起
        echarts.util.each(nodes, function (datum, index) {
            var key = datum.deptId;
            if (that.manuallyExpandDeptId.indexOf(key) > -1) {
                // 展开
                datum.collapsed = false
            } else {
                // 收起
                datum.collapsed = true
            }
        });
        for (var nodeIndex in nodes) {
            var node = nodes[nodeIndex];
            if (node.children) {
                that.syncExpandNode(node.children);
            }
        }
        return nodes;
    }
    
    // 初始化方法
    // this.deptTreeEchartsObj 是 echarts 对象
    if (this.deptTreeEchartsObj == null) {
        this.deptTreeEchartsObj = echarts.init(document.getElementById("deptTreeChart"));
        this.deptTreeEchartsObj.setOption(option);
    
        // 初始化默认展开的节点数据
        this.setDefaultExpandDeptId(data, 1);
    
        this.deptTreeEchartsObj.on('click', function (params) {
            var key = params.data.deptId;
            const index = that.manuallyExpandDeptId.indexOf(key);
            if (index > -1) {
                that.manuallyExpandDeptId.splice(index, 1);
            } else {
                that.manuallyExpandDeptId.push(key);
            }
        });
    
    } else {
        // 此方法需要在 setOption 之前调用
        // 因为 echarts.util.each 需要在  setOption 方法前调用
        this.syncExpandNode([data]);
        this.deptTreeEchartsObj.setOption(option, {
            replaceMerge: ['series']
        });
    }
  • 玩儿转 tooltips, 有一个需求,需要我们实现三点

    • echart 图形刷新的时候 tooltips 也丝滑刷新,不要让用户感觉到变化
    • 鼠标移到节点图标上可以显示
    • 鼠标移出节点图标可以隐藏

    此时,我们不能设置 tooltip.triggerOn: ‘mousemove’, 因为,这样设置的话,echarts 图形刷新的时候,mouseover 事件会消失,也就是 tooltips 会消失,此时需要再动一下鼠标,tooltips 才会出现, 所以我们只能设置 tooltip.triggerOn: ’none’, https://echarts.apache.org/zh/option.html#tooltip.triggerOn 此外,有时候,为了保证 echarts 图形刷新的时候,tooltip 也能不隐藏,会设置 tooltip.alwaysShowContent: true,这也是不行的,因为这种情况下,tooltip 根本无法隐藏 所以,最后我们最终的答案是,设置 tooltip.triggerOn 为 ’none’,然后通过 action.tooltip.showTip 和 action.tooltip.hideTip 来手动触发和隐藏 tooltip,其实在稍微复杂一点的场景下,我们都应该通过这种方式来控制,简单有效 下面来看怎么设置

    参考源文件-deptTree.html

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    
    option.tooltip:
    tooltip: {
        show: true,
        trigger: 'item',
        confine: true,
        triggerOn: 'none',
        // alwaysShowContent: true,
        enterable: true
    },
    
    // 刷新方法
    if (this.deptTreeEchartsObj == null) {
    
        this.deptTreeEchartsObj = echarts.init(document.getElementById("deptTreeChart"));
        this.deptTreeEchartsObj.setOption(option);
    
        .... 其他初始化逻辑 .... 
    
        this.deptTreeEchartsObj.on('click', function (params) {
            var key = params.data.deptId;
            const index = that.manuallyExpandDeptId.indexOf(key);
            if (index > -1) {
                that.manuallyExpandDeptId.splice(index, 1);
            } else {
                that.manuallyExpandDeptId.push(key);
            }
        });
    
        // ToolTips
        // 显示
        this.deptTreeEchartsObj.on('mouseover', function (params) {
            var dataIndex = params.dataIndex;
            that.toolTipsId = dataIndex;
            that.deptTreeEchartsObj.dispatchAction({
                type: 'showTip',
                seriesIndex: 0,
                dataIndex: that.toolTipsId
            });
        });
        // 隐藏
        this.deptTreeEchartsObj.on('mouseout', function (params) {
            that.toolTipsId = null;
            that.deptTreeEchartsObj.dispatchAction({
                type: 'hideTip'
            });
        });
    
    } else {
    
        .... 其他更新逻辑 .... 
    
        // 恢复 ToolTip 的显示
        if (this.toolTipsId) {
            this.deptTreeEchartsObj.dispatchAction({
                type: 'showTip',
                seriesIndex: 0,
                dataIndex: this.toolTipsId
            });
        }
    }
0%