• Vue中使用ECharts画散点图加均值线与阴影区域


    [本文出自天外归云的博客园]

    需求

    1. Vue中使用ECharts画散点图

    2. 在图中加入加均值线

    3. 在图中标注出阴影区域

    实现

    实现这个需求,要明确两点:

    1. 知道如何在vue中使用echarts

    2. 要知道如何在echarts散点图中画均值线和阴影区域

    在下面的代码option对象的series属性中用到了markLine和markArea,标注最值用到了markPoint。

    所以去官方文档搜索标线、标点、标图的关键字要搜mark。

    如何在vue中使用echarts见文末。

    需要注意的是vue的渲染时序,不要在页面没有渲染完就开始画图,那会找不到你定位id的元素。

    如何解决找不到元素的问题呢?网上说是在mounted函数中调用nextTick,这种方法可以试试,我是没成功。所以我自己发明的解法如下:

    以下的方法要放到vue文件的watch中,目的是监控showInfo和findAll两个变量的值的变化,一旦变量值变化则执行调用:

    showInfo: function() {
      // 元素显示了开始画线,待优化,可以细分到不用showInfo控制,用每个chart的v-if分别进行控制,因为有时候可能没有图表数据
      if (this.showInfo === true) {
        this.findAll = false
        this.timer = setInterval(() => {
          this.findElements()
        }, 1000)
      }
    },
    findAll: function() {
      if (this.findAll === true) {
        console.log('Timer stop.')
        clearInterval(this.timer)
      }
    }

    其中用到的变量都要在data函数中声明赋适当的初始值:

    1. this.showInfo控制页面元素的v-if显示开关,而showInfo变量的初始值一般为false,在mounted函数中我们可以把它的值设置为true,等页面加载完后打开显示开关

    2. this.timer是定时器,这里用到setInterval函数做一个定时的查询,用来定时查找页面上用来画echarts的div是否已经出现在页面,都找到了就停止定时查找

    3. this.findAll是一个signal,一旦为true说明所有元素都已找到,立即清空定时器this.timer,不再定时查询

    以下代码放到vue文件的methods中,是watch变量所用到的一些辅助函数:

    findElements() {
      if (this.findEleById('test_id_1')) {
        this.if_find_test_img_1_id = true
      }
      if (this.findEleById('test_id_2')) {
        this.if_find_test_img_2_id = true
      }
      if (this.findEleById('test_id_3')) {
        this.if_find_test_img_3_id = true
      }
      if (this.if_find_test_img_1_id && this.if_find_test_img_2_id && this.if_find_test_img_3_id) {
        this.findAll = true
      }
    },
    findEleById(ele_id) {
      var ele = document.getElementById(ele_id)
      if (ele !== null) {
        console.log('发现id为' + ele_id + '的元素')
        return true
      }
      return false
    }

    ECharts设置相关的核心代码如下:

    <template>
      <el-row>
        <el-col :span="24">
          <div id="chartDivId" :style="{ '100%', height: '500px'}"></div>
        </el-col>
      </el-row>
    </template>
    <script>
    export default{
      data() {
        return {
          imgData : {
            'columns': ['c1','c2','c3'],
            'rows': [
              {
                'c1': 'v1',
                'c2': 'v2',
                'c3': 'v3'
              },
            ],
            'mean': 2,
            'y_top': 3,
            'y_bottom': 1
          },
          methods: {
            // 画图函数,传入散点图所在div的id和图表数据
            drawImgChart(chartDivId, imgData) {
              // 基于准备好的dom,初始化echarts实例
              const myChart = this.$echarts.init(document.getElementById(chartDivId))// 绘制图表
              var option = {
                tooltip: {
                  trigger: 'axis',
                  showDelay: 0,
                  axisPointer: {
                    show: true,
                    type: 'cross',
                    lineStyle: {
                      type: 'dashed',
                       1
                    }
                  }
                },
                visualMap: {
                  min: 0,
                  max: imgData.mean, // 渐变色最深色对应的y轴坐标
                  dimension: 1,
                  precision: 3,
                  orient: 'vertical',
                  right: 10,
                  top: 'center',
                  text: ['HIGH', 'LOW'],
                  calculable: true,
                  inRange: {
                    color: ['#f2c31a', '#24b7f2']
                  }
                },
                xAxis: [
                  {
                    type: 'category',
                    show: false,
                    scale: true,
                    splitLine: {
                      show: true
                    },
                    data: imgData.columns, // x轴的数据
                    axisLabel: {
                      interval: 0,
                      rotate: 70
                    }
                  }
                ],
                yAxis: [
                  {
                    type: 'value',
                    scale: true,
                    splitLine: {
                      show: true
                    },
                    axisLabel: {
                      formatter: '{value} s' // y轴数据的格式 xx s
                    }
                  }
                ],
                series: [
                  {
                    type: 'scatter',
                    symbolSize: 5,
                    data: imgData.rows,
                    // 设置最大值点和最小值点
                    markPoint: {
                      data: [
                        { type: 'max', name: '最大值' },
                        { type: 'min', name: '最小值' }
                      ]
                    },
                    // 设置平均值线
                    markLine: {
                      lineStyle: {
                        normal: {
                          type: 'solid'
                        }
                      },
                      data: [
                        {
                          name: '平均值线',
                          yAxis: imgData.mean // 数值类型,对应y轴坐标
                        }
                      ]
                    },
                    // 设置阴影区域
                    markArea: {
                      silent: true,
                      itemStyle: {
                        normal: {
                          color: '#E8E8E8',
                          borderWidth: 1,
                          borderType: 'dashed'
                        }
                      },
                      data: [[{
                        name: '正常值范围区间',
                        yAxis: imgData.y_top // 阴影区域上边界
                      }, {
                        yAxis: imgData.y_bottom // 阴影区域下边界
                      }]]
                    }
                  }
                ]
              }
              myChart.setOption(option)
            }
          }
        }
      }
    }

    谈谈封装

    有时候封装的不好不如不封装,封装对外的接口如果不是大家需要的功能,反而相当于给被封装的对象关上了一道门,拒人于封装之外。

    比如eleme和baidu维护的两版针对vue使用的vchart,我觉得现在的封装程度就是能用一些echart的基本功能,很多细节都没有封装好。

    所以,即使vue不推荐直接操作dom元素,但是这次要在散点图中画线我还是选择用原装的echarts。

    更多资料

    1. ECharts官网在线调试散点图

    2. Vue项目中如何使用ECharts

  • 相关阅读:
    MongoDB笔记: 安装和常见问题
    Spring Boot方式的Dubbo项目
    Centos7安装Redis5.0.5并加入Systemd服务
    生成Nginx服务器SSL证书和客户端证书
    OpenSSL的证书, 私钥和签名请求(CSRs)
    迁移Git项目到Gitlab
    Ubuntu18.04 Server安装Nginx+Git服务和独立的svn服务
    ESXi6.5上的Ubuntu虚机在远程SSH时宕机
    Nginx访问路径添加密码保护
    从阿里云DATAV GeoAtlas接口抽取行政区划数据
  • 原文地址:https://www.cnblogs.com/LanTianYou/p/9679186.html
Copyright © 2020-2023  润新知