vuejs+echarts实现x轴为时间轴且数据区域可缩放

发布时间 2023-12-28 15:54:11作者: 我爱敲代码0000

1、效果图

2、具体功能描述

①选择的时间为时间轴的开始和结束时间;

②鼠标可以左右拖动x轴时间轴;

③鼠标放入图表中可以缩放数据,x轴会相应的更改当前坐标轴间隔值,最小间隔值为1分钟,最大间隔值为1年,且在缩放时可以获取到数据窗口范围的起始数值;

④点击y轴名称会对相应数据显示隐藏。

3、实现

①结构代码:

<div id="echart" style="width:100%;height: 240px;" ></div>
②配置图表
data () {
    return {
      option:{
        grid: {
          show: true,
          top: 15,
          left: 100,
          right: 30,
          bottom:30,
          backgroundColor:{
            image:require('../../../../../assets/image/default/echart_bg.png')
          },
          borderWidth:0,
        },
        tooltip: {
          trigger: 'item',
          formatter:function(params){
            return params.data[2] == 'transparent'?'':`${params.name}<br/>${params.data[0]}`
          },
        },
        xAxis: {
          type: 'time',
          maxInterval: 3600 * 1000 * 24 * 30 * 12,//设置间隔最大值
          minInterval:1000 * 60 * 2,//设置间隔最小值
          axisLine: {
            // 轴线
            show: true,
          },
          axisTick: {
            // 轴刻度
            show: true,
            alignWithLabel: true,
          },
        },
        yAxis: {
          data: [],
          axisLine: {
            // 轴线
            show: false,
          },
          axisTick: {
            // 轴刻度
            show: false,
          },
          splitLine: {
            // 网格线
            show: true,
            alignWithLabel: true,
            lineStyle:{
              color:'#ccc'
            }
          },
          triggerEvent:{
            show: true,//点击事件
          },
        },
        series: [
          {
            type: 'scatter',
            smooth: true,
            symbol: 'circle',
            symbolSize: 20,
            sampling: 'average',
            itemStyle:{
              color:(val)=>{
                return val.data[2]
              },
              opacity:1
            },
            data: []
          }
        ],
        dataZoom: [
          {
            type: 'inside',//内置型数据区域缩放组件
            xAxisIndex: 0,
            filterMode: 'filter',//过滤掉窗口外的数据
            realtime: true,
          },
        ],
      },
      myChart:null,
      dataList:[],//颜色集合
      dataValue:[],//数据集合
    };
  },
③初始化图表
    initEchart() {
      let that = this;
      let scale = '1年';//间隔值
      let queryTimePeriodLimit = {
        startTime:null,
        endTime:null,
      }
      // 基于准备好的dom,初始化echarts实例
      this.myChart = this.$echarts.init(document.getElementById("echart"));
      //this.ruleForm.spatialTrajectoryTime为时间范围选择值,如何存在则为时间轴起始值否则开始值为当前-8年结束值为当前+2年
      if(this.ruleForm.spatialTrajectoryTime && this.ruleForm.spatialTrajectoryTime.length > 0 && this.ruleForm.spatialTrajectoryTime[0].queryTimePeriodLimit){
        this.option.xAxis.min = new Date(this.ruleForm.spatialTrajectoryTime[0].queryTimePeriodLimit[0]).getTime();
        this.option.xAxis.max = new Date(this.ruleForm.spatialTrajectoryTime[0].queryTimePeriodLimit[1]).getTime();
      }else{
        this.option.xAxis.min = new Date().getTime()-8*12*30*24*60*60*1000;
        this.option.xAxis.max = new Date().getTime()+2*12*30*24*60*60*1000;
      }
  //获取当前间隔值
      scale = that.handleTimeAndScale(this.option.xAxis.min,this.option.xAxis.max,'init');
      // 绘制图表
      this.myChart.setOption(this.option,true);
      window.addEventListener("resize", () => {
        that.myChart.resize();
      });
      this.$emit('getScale',scale,'init');//调用接口获取当前值渲染图表
      this.myChart.on('dataZoom',function(params){
        let startValue = parseInt(that.myChart.getModel().option.dataZoom[0].startValue);
        let endValue = parseInt(that.myChart.getModel().option.dataZoom[0].endValue);
        queryTimePeriodLimit.startTime = that.dateFormatter('yyyy-MM-dd HH:mm:ss',new Date(startValue));
        queryTimePeriodLimit.endTime = that.dateFormatter('yyyy-MM-dd HH:mm:ss',new Date(endValue));
        scale = that.handleTimeAndScale(startValue,endValue);
        //缩放、拖动时间轴后调用接口获取当前值渲染图表
      })
      that.myChart.off('click');//先移除,再点击
      that.myChart.on('click', function (params) {
   //点击y轴
        if(params.componentType == 'yAxis'){
          that.dataList[params.tickIndex].clicked = !that.dataList[params.tickIndex].clicked;
          that.dataValue.map((value,key)=>{
            if(value[3] == params.dataIndex){
              if(that.dataList[params.tickIndex].clicked){
                // 显示时间轴数据
                value[2] = that.colorList[params.dataIndex];
              }else{
                // 隐藏时间轴数据
                value[2] = 'transparent';
              }
            }
          })
          that.myChart.setOption({yAxis:that.setYaxisIcon(that.dataList)});//设置y轴样式
          that.myChart.setOption({series:that.option.series[0]});
        }
      });
    },
    // 渲染数据
    getEchartsData(dataList){
      let that = this;
      let data = [];
      this.dataValue = [];
      this.dataList = dataList;
      this.dataList.map((item,index)=>{
        data.push(item.entityName+'-'+item.propertyTypeName);
        if(item.locus && item.locus.length > 0){
          item.locus.map((list,pre)=>{
            if(list.locus && list.locus.length > 0 ){
              list.locus.map((value,key)=>{
      //第一个值为x轴值,第一个值为y轴名称,第三个值为颜色,第四个值为索引...需要什么值可在此位置添加
                that.dataValue.push([value.startTime,item.entityName+'-'+item.propertyTypeName,(item.clicked?(that.colorList[index]):'transparent'),index]);
              })
            }
          })
        }
      })
      that.option.yAxis.data = data;
      that.setYaxisIcon(that.dataList);
      that.option.series[0].data = that.dataValue;
      that.myChart.setOption({yAxis:that.option.yAxis});
      that.myChart.setOption({series:that.option.series[0]});
    },
 //在数据区域缩放时能获取数据窗口范围的起始数值,利用起始值可以获取到起始值的差值,根据差值的大小来设置当前的间隔值
 //(由于x轴type为time所以x轴的scale值无效,获取不到比例尺所以想出此方法)
  handleTimeAndScale(startValue,endValue,type){
      let that = this;
      let scale = '';
      let intervalValue = null;
      let interval = (endValue - startValue)/1000/60/60;
      if(interval > 44336){
        intervalValue = 3600 * 1000 * 24 * 30 * 12;
        scale = '1年';
      }else if(interval <= 44336 && interval > 27529){
        intervalValue = 3600 * 1000 * 24 * 30 * 7;
        scale = '6月';
      }else if(interval <= 27529 && interval > 14127){
        intervalValue = 3600 * 1000 * 24 * 30 * 4;
        scale = '3月';
      }else if(interval <= 14127 && interval > 8771){
        intervalValue = 3600 * 1000 * 24 * 30 * 3;
        scale = '2月';
      }else if(interval <= 8771 && interval > 3381){
        intervalValue = 3600 * 1000 * 24 * 30 * 1;
        scale = '1月';
      }else if(interval <= 3381 && interval > 2309){
        intervalValue = 3600 * 1000 * 24 * 17;
        scale = '16天';
      }else if(interval <= 2309 && interval > 1095){
        intervalValue = 3600 * 1000 * 24 * 8;
        scale = '7天';
      }else if(interval <= 1095 && interval > 511){
        intervalValue = 3600 * 1000 * 24 * 5;
        scale = '4天';
      }else if(interval <= 511 && interval > 222){
        intervalValue = 3600 * 1000 * 24 * 3;
        scale = '2天';
      }else if(interval <= 222 && interval > 125){
        intervalValue = 3600 * 1000 * 24 * 1;
        scale = '1天';
      }else if(interval <= 125 && interval > 73){
        intervalValue = 3600 * 1000 * 13;
        scale = '12时';
      }else if(interval <= 73 && interval > 37){
        intervalValue = 3600 * 1000 * 7;
        scale = '6时';
      }else if(interval <= 37 && interval > 22){
        intervalValue = 3600 * 1000 * 5;
        scale = '4时';
      }else if(interval <= 22 && interval > 12){
        intervalValue = 3600 * 1000 * 3;
        scale = '2时';
      }else if(interval <= 12 && interval > 4.4){
        intervalValue = 3600 * 1000 * 1;
        scale = '1时';
      }else if(interval <= 4.4 && interval > 3){
        intervalValue = 1000 * 60 * 31;
        scale = '30分钟';
      }else if(interval <= 3 && interval > 2){
        intervalValue = 1000 * 60 * 21;
        scale = '20分钟';
      }else if(interval <= 2 && interval > 1.5){
        intervalValue = 1000 * 60 * 16;
        scale = '15分钟';
      }else if(interval <= 1.5 && interval > 1){
        intervalValue = 1000 * 60 * 11;
        scale = '10分钟';
      }else if(interval <= 1 && interval > 0.5){
        intervalValue = 1000 * 60 * 6;
        scale = '5分钟';
      }else if(interval <= 0.5 && interval > 0.2){
        intervalValue = 1000 * 60 * 3;
        scale = '2分钟';
      }else if(interval <= 0.2){
        intervalValue = 1000 * 60 * 2;
        scale = '1分钟';
      }
      if(type && type == 'init'){
        that.option.xAxis.interval = intervalValue;
      }else{
        that.myChart.setOption({xAxis:{interval:intervalValue}});
      }
      return scale
    },
 // 设置y轴图标
    setYaxisIcon(nodes){
      let that = this;
      that.option.yAxis.axisLabel = {
        formatter: function (value,index) {
          return '{nodeName|' + (nodes[index].entityName.length>5?(nodes[index].entityName.slice(0,5)+'...'):nodes[index].entityName) + `}{${nodes[index].clicked?'image':'imageClicked'}|` + '}\n{propertyTypeName|' + (nodes[index].propertyTypeName.length>5?(nodes[index].propertyTypeName.slice(0,5)+'...'):nodes[index].propertyTypeName) + '}';
        },
        rich: {
          nodeName:{
            fontWeight:700,
            padding: [0, 6 , 0 , 0],
            align: 'left',
            color:'#000'
          },
          image: {
            width:14,
            height: 14,
            cursor: 'pointer',
            backgroundColor: {
              image: require('../../../../../assets/image/default/clickedEye.png'),
            },
          },
          imageClicked: {
            width:14,
            height: 14,
            cursor: 'pointer',
            backgroundColor: {
              image: require('../../../../../assets/image/default/clickEye.png'),
            },
          },
          propertyTypeName: {
            lineHeight: 30,
            align: 'left',
          },
        },
      }
    },