• Echarts柱状图label优化历程


    问题1

    由于项目数据记录多或者数据值大的时候,会出现label重叠的现象,如下图。

    解决方案

    针对上述问题,解决思路如下:

    1、求Y轴的最大值(我们用Y轴的最大值,去计算每个柱子在整个图中的占比)

    2、计算每个数据的占比

    3、占比小于某个值的label,向上移动一定距离

    技术实现

    求Y轴的最大值

    由上图可知,我们有计划值、完成值两组数据,且这两组值共用一个Y轴。

    上图为观察的5组数据的值。

    echarts默认分割段数为5,为了计算最大值,我们还默认为5。刚开始从网上找了一个求最大值的公式,计算后如上图的第一行,发现步长不好看,有可能还会有小数。

    后来使用echarts默认的最大值,为上图第二行。

    数据的最大值为上图的第三行。

    最大值的步长为第四行。

    默认步长为第五行。

    经观察及多次试验发现步长可通过如下公式计算:

    1. // 获取步长
    2. const getStep = (value, count) => { // count是计算的层数
    3. let num = Math.ceil(value / 10);
    4. return num > 15 ? getStep(num, count + 1) : num * Math.pow(10, count);
    5. }
    6. // 求最大值
    7. let stepVal = getStep(_.max(dataList) / 5, 1); // dataList - 计划值、完成值组成的数组
    8. maxVal = stepVal * 5;

    计算每个数据的占比

    经上步可计算出每个数据在整个图中的占比。

    1. let planRatio = parseFloat((plan / maxVal * 100).toFixed(2)); // 计划比
    2. let nowRatio = parseFloat((now / maxVal * 100).toFixed(2)); // 完成比

    移动label

    通过各数据的占比,计算两者之间的差值,当差距小于n时,让该值的label向上移动。

    1. // 移动label
    2. data1.forEach((item, index) => {
    3. let planRatio = parseFloat((item / maxVal * 100).toFixed(2)); // 计划比
    4. let nowRatio = parseFloat((data2[index] / maxVal * 100).toFixed(2)); // 完成比
    5. let nowVal;
    6. if (data2[index] === 0) {
    7. nowVal = data2[index];
    8. } else { // 两个比值小于5,错落显示
    9. nowVal = Math.abs(nowRatio - planRatio) < 4 ? {value: data2[index], label: {offset: [0, -20]}} : data2[index];
    10. }
    11. option.series[0].data.push(item);
    12. option.series[1].data.push(nowVal);
    13. })

    最终效果图

    问题2

    为了视觉上更直观,客户要求将平面柱状图改成立体柱状图,效果如下。

     

    思路

    普通柱状图(bar)+ 象形柱图(pictorialBar)

     难点1

    由于数据是不固定的,所以当数据量大的时候,普通柱状图的柱子宽度会自适应,而象形图的大小确是固定的,所以会出现顶部椭圆和柱子宽度不匹配的现象,如下图

     

    解决方案

    根据数据长度,动态设置象形图的大小及偏移位置。

    1. // 不同数据长度对应不同柱子宽度
    2. const getSymbolSize = () => {
    3. let len = dataName.length;
    4. switch (len) {
    5. case 6:
    6. return [24, 10];
    7. case 7:
    8. return [20, 8];
    9. case 8:
    10. return [18, 8];
    11. default:
    12. return [24, 10];
    13. }
    14. }
    15. // 不同数据长度对应不同柱子偏移
    16. const getSymbolOffset = (i) => {
    17. let len = dataName.length;
    18. switch (len) {
    19. case 6:
    20. return i === 2 ? [-12, -6] : [12, -6];
    21. case 7:
    22. return i === 2 ? [-11, -5] : [11, -5];
    23. case 8:
    24. return i == 2 ? [-9, -5] : [9, -5];
    25. default:
    26. return i === 2 ? [-12, -6] : [12, -6];
    27. }
    28. }

    难点2

    在echarts图中,z值控制图形的前后顺序。z值小的图形会被z值大的图形覆盖。由于象形图的z值比柱状图的z值大,所以会把柱状图的label值给覆盖了,如下图。

    解决方案

    将label值根据数据的大小动态的显示到柱状图或者象形图上。

    PS:不可以直接显示到象形图上,因为数据值很小的情况只看到了象形图,所以不显示象形图

     

  • 相关阅读:
    计算机毕业设计Python+Django的学生作业管理系统
    vue 导入、导出模块的几种方式
    【翻译】Texture Synthesis Using Convolutional Neural Networks
    【ML】Q-Learning应用于具有连续状态的问题(Q-Learning 学习滑冰)
    【Linux】进程控制
    编译原理—语义分析、语法制导翻译、翻译模式、中间代码生成
    使用 message buffer 传递数据
    案例题-软件架构设计
    postman调用后台接口,response是html,状态码是200
    【C++进阶学习】第六弹——set和map——体会用C++来构建二叉搜索树
  • 原文地址:https://blog.csdn.net/u010753613/article/details/128084870