关于echarts图表的一点总结

1,467 阅读3分钟

最近项目中使用了比较多的echarts图表元素,遇到了一些问题,有些通过查询官方文档可以很快解决,有些就没那么容易了,故记录下!

先放一张图

问题1:在legend(图例组件)值不固定的情况下,保证柱状图展示正常

先介绍下背景,这里的柱状图是子组件,通过prop,父组件向子组件传值,并在子组件中使用watch监听传入数据的变化

这里给出子组件中的监听代码:

watch: {
    data: {
      handler(nv, ov) {
        if (this.chart) {
          this.chart.setOption(
            {
              ...this.defaultOption,
              series: [...this.series],
              dataset: {
                ...nv
              }
            }
          )
        } else {
          this.initChart()
        }
      },
      deep: true
    }
  },

一开始,图表也很正常,直到多了一种legend数据

可以看出,这里的数据已经乱了,抛开颜色的问题,这里多的legend类型是已恢复,但是却没有正常渲染,我查看了传入的数据也是正常的,那么问题到底出在哪里呢?

经过一番网络查询,找出了一点眉目,使用echarts实例方法setOption更新配置的话,默认是合并参数和数据的,所以我们应该将其设置成不合并

watch: {
    data: {
      handler(nv, ov) {
        if (this.chart) {
          this.chart.setOption(
            {
              ...this.defaultOption,
              series: [...this.series],
              dataset: {
                ...nv
              }
            },
            true
          )
        } else {
          this.initChart()
        }
      },
      deep: true
    }
  }

经过测试,问题解决。

还没来的急高兴一波,新的问题来了,看图

问题2:如何实现如图所示的效果

查询了echarts文档,没有找到相关的实例,没办法,再一次网上找资料,经过漫长的搜寻,终于又让我找到了解决方案,那就是通过echarts设置自定义图形,这里的代码是直接copy经过简单的修改,但参考地址我忘记了,就不放连接了

var MyCubeRect = echarts.graphic.extendShape({
  shape: {
    x: 0,
    y: 0,
    width: 36 // 柱宽
    // zWidth: 8, // 阴影折角宽
    // zHeight: 4 // 阴影折角高
  },
  buildPath: function(ctx, shape) {
    const api = shape.api
    const xAxisPoint = api.coord([shape.xValue, 0])
    const p0 = [shape.x, shape.y]
    const p1 = [shape.x - shape.width / 2, shape.y]
    const p4 = [shape.x + shape.width / 2, shape.y]
    const p2 = [xAxisPoint[0] - shape.width / 2, xAxisPoint[1]]
    const p3 = [xAxisPoint[0] + shape.width / 2, xAxisPoint[1]]

    ctx.moveTo(p0[0], p0[1]) // 0
    ctx.lineTo(p1[0], p1[1]) // 1
    ctx.lineTo(p2[0], p2[1]) // 2
    ctx.lineTo(p3[0], p3[1]) // 3
    ctx.lineTo(p4[0], p4[1]) // 4
    ctx.lineTo(p0[0], p0[1]) // 0
    ctx.closePath()
  }
})
var MyCubeShadow = echarts.graphic.extendShape({
  shape: {
    x: 0,
    y: 0,
    width: 36,
    zWidth: 8,
    zHeight: 6
  },
  buildPath: function(ctx, shape) {
    const api = shape.api
    const xAxisPoint = api.coord([shape.xValue, 0])
    // const p0 = [shape.x, shape.y]
    const p1 = [shape.x - shape.width / 2, shape.y]
    const p4 = [shape.x + shape.width / 2, shape.y]
    const p6 = [
      shape.x + shape.width / 2 + shape.zWidth,
      shape.y - shape.zHeight
    ]
    const p7 = [
      shape.x - shape.width / 2 + shape.zWidth,
      shape.y - shape.zHeight
    ]
    const p3 = [xAxisPoint[0] + shape.width / 2, xAxisPoint[1]]
    const p5 = [
      xAxisPoint[0] + shape.width / 2 + shape.zWidth,
      xAxisPoint[1] - shape.zHeight
    ]

    ctx.moveTo(p4[0], p4[1]) // 4
    ctx.lineTo(p3[0], p3[1]) // 3
    ctx.lineTo(p5[0], p5[1]) // 5
    ctx.lineTo(p6[0], p6[1]) // 6
    ctx.lineTo(p4[0], p4[1]) // 4

    ctx.moveTo(p4[0], p4[1]) // 4
    ctx.lineTo(p6[0], p6[1]) // 6
    ctx.lineTo(p7[0], p7[1]) // 7
    ctx.lineTo(p1[0], p1[1]) // 1
    ctx.lineTo(p4[0], p4[1]) // 4
    ctx.closePath()
  }
})
echarts.graphic.registerShape('MyCubeRect', MyCubeRect)
echarts.graphic.registerShape('MyCubeShadow', MyCubeShadow)

//其他配置项省略
series: [
          {
            type: 'custom',
            renderItem: function(params, api) {
              const location = api.coord([api.value(0), api.value(1)])
              return {
                type: 'group',
                children: [
                  {
                    type: 'MyCubeRect',
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1]
                    },
                    style: {
                      fill: '#1bc4eb'
                    }
                  },
                  {
                    type: 'MyCubeShadow',
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1]
                    },
                    style: {
                      fill: '#1496b3'
                    }
                  }
                ]
              }
            }
          }
        ]

实际效果如下:

还是比较接近的,那么这个问题也解决!

好的,新的问题

问题3:横坐标数据动态变化的情况下,正常展示

因为在问题二中,柱子的图形是通多自定义图形绘制的,所以图形的位置啥的都是按照目前的画布来的,突然多了一组数据,图形位置什么就会错乱。本来觉得按照问题一的解法应该可以解决问题,但并无卵用,所以就找找资料呗,我的想法是,如果不能更新图形,不如在每次数据变化的时候,先清空画布在重新绘制

这里的方案如下:

watch: {
    data(nv, ov) {
      this.chart.clear()
      this.chart.setOption({
        ...this.defaultOption,
        dataset: {
          ...this.data
        }
      })
    }
  }

终于,收工!

各位如果有其他的解法,也请告知,路漫漫其修远兮,吾将上下而求索!