echarts可上下拖动折线图(多条线)

3,250 阅读2分钟

可交互式且存在多条折线分别拖动的图表

示例图如下,以下图中的每个点都可分别拖动

以下为代码

<template>
  <div>
    <div ref="sszs" style="height:400px;"></div>
  </div>
</template>

<script>
var symbolSize = 10;
var color = [
  "#c23531",
  "#2f4554",
  "#61a0a8",
  "#d48265",
  "#91c7ae",
  "#749f83",
  "#ca8622",
  "#bda29a",
  "#6e7074",
  "#546570",
  "#c4ccd3"
];
var data = [[0, 22], [10, 38], [20, 60], [30, 90], [40, 88]];//数据格式
let arr = [];
let dataarr = [];
for (let i = 0; i < 20; i++) {
  arr.push([
    [0, Math.round(Math.random() * 100)],
    [10, Math.round(Math.random() * 100)],
    [20, Math.round(Math.random() * 100)],
    [30, Math.round(Math.random() * 100)],
    [40, Math.round(Math.random() * 100)]
  ]);
}
arr.forEach((el, i) => {
  dataarr.push({
    name: "b" + i,
    id: "b" + i,
    type: "line",
    symbol: i > 10 ? "none" : "emptyCircle",
    symbolSize: symbolSize,
    data: el,
    lineStyle: {
      width: 2,
      color: i > 10 ? "#999" : color[i]
    }
  });
});

function reduceDimension(arr) {
  return Array.prototype.concat.apply([], arr);//数据降维
}

import echarts from "echarts";
export default {
  data() {
    return {
      option: {
        title: {
          text: "Try Dragging these Points"
        },
        //测试legend的代码,没找到合适的解决办法
        // legend: {
        //   data: ["b0", "b1"],
        //   left: "center",
        //   // bottom: '10%',
        //   itemWidth: 10, //图例的宽度
        //   itemHeight: 10, //图例的高度
        //   textStyle: {
        //     //图例文字的样式
        //     color: "#999",
        //     fontSize: 16
        //   },
        //   formatter: function(a) {
        //     console.log(a, "===");
        //     return datax[a.split("b")[1]];
        //   },
        //   z: 2000
        // },
        tooltip: {
          triggerOn: "none",
          formatter: function(params) {
            return (
              "X: " +
              params.data[0].toFixed(2) +
              "<br>Y: " +
              params.data[1].toFixed(2)
            );
          }
        },
        grid: {},
        xAxis: {
          type: "value",
          axisLine: {
            onZero: false
          }
        },
        yAxis: {
          type: "value",
          axisLine: {
            onZero: false
          }
        },
        series: dataarr
      },
      chart: [],
      obj: {}
    };
  },
  mounted() {
    let that = this;
    let myChart = echarts.init(this.$refs.sszs);
    function updatePosition() {
      myChart.setOption({
        graphic: reduceDimension(
          arr.map((el, i) =>
            echarts.util.map(el, function(item, dataIndex) {
              return {
                position: myChart.convertToPixel("grid", item)
              };
            })
          )
        )
      });
    }

    function onPointDragend(dataIndex, i) {
      arr[i][dataIndex] = myChart.convertFromPixel("grid", this.position);
      //执行保存数据相关操作
    }

    function showTooltip(dataIndex, b) {
      myChart.dispatchAction({
        type: "showTip",
        seriesIndex: b,
        dataIndex: dataIndex
      });
    }

    function hideTooltip(dataIndex) {
      myChart.dispatchAction({
        type: "hideTip"
      });
    }

    function onPointDragging(dataIndex, dx, dy) { //dx,dy本来以为有默认参数,结果没有,但echarts demo上面有,咱也不知道是啥,也没地问
      let origin = myChart.convertToPixel("grid", arr[dx][dataIndex]);
      if (this.position[1] > 340) {//控制上下拖动范围 跟ref高度有关
        this.position[1] = 340;
      } else if (this.position[1] < 60) {
        this.position[1] = 60;
      }
      this.position[0] = origin[0];
      arr[dx][dataIndex] = myChart.convertFromPixel("grid", this.position);

      myChart.setOption({//图表重绘
        series: [
          {
            id: "b" + dx,
            data: arr[dx]
          }
        ]
      });
    }

    window.onresize = myChart.resize;
    myChart.setOption(this.option);
    var num = 0;
    setTimeout(function() {
      // Add shadow circles (which is not visible) to enable drag.
      myChart.setOption({
        graphic: reduceDimension( //绘制多条线的关键!关键!关键!,自己套数据格式
          arr.map((el, i) => {
            if (i > 10) {//筛选拖动线的条件,可自行配置 
              return;
            }
            return echarts.util.map(el, function(item, dataIndex) {
              return {
                type: "circle",
                position: myChart.convertToPixel("grid", item),
                shape: {
                  cx: 0,
                  cy: 0,
                  r: symbolSize / 2
                },
                invisible: true,
                draggable: true,
                ondrag: echarts.util.curry(onPointDragging, dataIndex, i),
                ondragend: echarts.util.curry(onPointDragend, dataIndex, i),
                onmousemove: echarts.util.curry(showTooltip, dataIndex, i),
                onmouseout: echarts.util.curry(hideTooltip, dataIndex),
                z: 100
              };
            });
          })
        )
      });
    }, 0);
    window.addEventListener("resize", updatePosition);
  }
};
</script>

指导思想即 折线和点的关联并不密切,点的坐标是通过数据确定的,所以数据格式不好轻易变动,这也是为什么有些麻烦的地方难处理的原因,重新绘制原理一样。

以上仅为鄙人拙见,如有雷同不胜荣幸,欢迎各位大佬指指点点。

存在的问题

1,legend以及x轴label不好处理 2,线条过多有明显性能问题