• echarts折线图如何防止label重叠,实现一上一下的效果


    网上参考了很多答案,基本都没用。问过几个同事也没有现成的解决方案,有方案也大多不完美。我们要实现的效果是label标签全部显示并实现一上一下,完成结果如图所示,想了很久,代码不是很难,难的是实现的思路。

    如图:
    折线图一上一下效果
    要实现上图的效果,我想过几种思路:

    1. 获取同一坐标轴上的坐标点,然后对比同一纬度的大小给设置positon方式。

      事实证明行不通,首先坐标我查阅文档查了半天也在网上进行搜索,都是答非所问。其次,就算坐标找到了,没有办法直接在option的label里动态设置positon. 官方文档似乎就几种固定的属性,没有看到position有设置回调的方法。

    2. 文档也看了好几遍了,也没发现可以动态设置offset的方式,试过了不行。接下来说可以实现的方式。

    3. 实现思路
      3-1. 在异步获取折线图数据时添加一个标记position,这个标记表示当前数据在图标中的位置是上还是下。
      3-2. 举个例子,用当前值和同期值做对比,如果当前值大于同期值,那么数值应该在上方,反之下方。
      3-3. 有个值得注意的点是,折线图不设置position时默认都是top,所以我们只要对标记为bottom的数值做位置上的处理就行。
      3-4. 最后通过设置padding的方式实现了。

    具体实现代码如下:

        const queryCargoTrendData = async (chartParams) => {
            try {
                lineOption.series[0].data = []
                lineOption.series[1].data = []
                const { data } = await queryCargoTrend(chartParams)
                if (data.records && data.records.length > 0) {
                	lineOption.xAxis.data = data.records.map(item => item.dateCode)
                    data.records.forEach(item => {
                        /***
                         * 0 注释很重要,必看
                         * 1 通过遍历的方式给series的两个数组分别添加 position 标记
                         *      position1 表示当月数据在折线图中的上下位置
                         *      position2 表示同期数据在折线图中的上下位置
                         * 2 添加好标记后去label的formatter格式化函数进行数据处理
                         * 
                        */
                        let position1 = item.value > item.valuelwd ? 'top':'bottom'
                        let position2 = item.value > item.valuelwd ? 'bottom':'top'
                        
                        /***
                         * 3 这里有个注意的地方,如果数据映射到图标,那么必须得有个字段是value,否则不显示,
                         * 其他的随便你怎么加,不清楚就按照下面的添加
                         */
                        lineOption.series[0].data.push({value: item.value, position: position1})
                        lineOption.series[1].data.push({value: item.valuelwd, position: position2})
                    })
                }
    
            } catch (e) {}
        }
    

    重要的事说一遍,先看注释!,接下来对标记的数据进行处理,完整代码太长,这里只贴有用的部分,如果还有不明白的可以留言问我。

            series: [
                {
                    name: '每日数据',
                    type: 'line',
                    color: '#7C25FF',
                    label: {
                        show: true,
                        color: colors[0],
                        formatter: (params) => { // 实现
                            /***
                             * data 映射的数据源; value 折线图实际取值; 《如果实在不明白请查阅文档》
                             * 这里有个点,上文说过了,由于默认position的位置是‘top’, 
                             * 所以这里只需对bottom位置的数据进行处理
                             * 最后通过rich给样式设置padding可以实现。
    							
                             */
                            const { data, value } = params;
                            let arr = data.position == 'bottom' ? ['{bottom|'+ value +'}'] : [value];
                            return arr.join('')
                        },
                        textStyle: {
                            rich: {
                                bottom: {
                                    padding: [0, 0, -50, 0]
                                },
                            }
                        }
                    },
                    symbol: 'circle',
                    symbolSize: 8,
                    lineStyle: {
                        width: 1
                    },
                    itemStyle: {
                        borderWidth: 1,
                        borderColor: '#fff',
                    },
                    data: []
                },
                {
                    name: '上周同期',
                    type: 'line',
                    color: '#ffa65e',
                    label: {
                        show: true,
                        color: colors[1],
                        formatter: (params) => {
                            // data 映射的数据源; value 折线图实际取值;
                            const { data, value } = params;
                            let arr = data.position == 'bottom' ? ['{bottom|'+ value +'}'] : [value]
                            return arr.join('')
                        },
                        textStyle: {
                            rich: {
                                bottom: {
                                    padding: [0, 0, -50, 0]
                                }
                            }
                        }
                    },
                    symbol: 'circle',
                    symbolSize: 8,
                    lineStyle: {
                        width: 1
                    },
                    itemStyle: {
                        borderWidth: 1,
                        borderColor: '#fff',
                    },
                    data: []
                }
            ],
            dataZoom: {
                type:'inside',
                orient: 'horizontal',
                start: 0,
                end: 20,
                height: 12,//组件高度
                borderColor: "#F4F4F4",
                zoomLock: true,
            }
    

    以上基本就可以实现如图的效果了。

    还是那句话:

    花费了一些时间,抱着分享的心态来分享一下心得,希望不要转载
    对你有帮助的话麻烦点个赞或收藏,感激,赠人玫瑰,手有余香🌹

  • 相关阅读:
    【分布式】分布式中间件RabbitMQ、 cache注解
    【每日一题Day343】LC2731移动机器人 | 脑筋急转弯+数学
    NodeJs实战-Express构建照片存储网站(1)-ejs视图引擎填充数据
    【Java 基础篇】Java标准输入流详解:读取用户输入的完整指南
    了解一下pnpm
    【HMS Core】定位地图服务常见问题,穿戴设备支持、比例尺支持、在非华为手机上逆地理编码的支持?
    vue v-model与.sync详解
    C. Monoblock(思维/计数)
    软件培训测试高级工程师多测师肖sir__html之作业11
    Flutter ーー logger 组件记录日志
  • 原文地址:https://blog.csdn.net/qq_40128375/article/details/127094837