echarts上散点图与提示框间需要一条曲线连接

30 阅读1分钟

今天收到别人的一个问题,百度了下竟然发现csdn 没有类似的解答,然后花了2小时研究了下,给大家分享下。 demo效果

GIF 2023-8-29 15-06-33.gif 废话少说直接上代码截图:

<template>
  <div class="scatter-container">
    <div ref="scatterChart" class="scatter-chart"></div>
    <div ref="tooltipBox" class="tooltip-box">
      <p>{{ tooltipData.name }}</p>
    </div>
    <svg ref="lineContainer" class="line-container"></svg>
  </div>
</template>

<script>
import * as echarts from "echarts";

export default {
  data() {
    return {
      scatterData: [
        { name: 'Point A', value: [0, 0] },
        { name: 'Point A', value: [50, 50] },
        { name: 'Point A', value: [100, 100] },
        { name: 'Point B', value: [200, 200] },
        { name: 'Point C', value: [300, 200] },
        { name: 'Point D', value: [400, 200] },
        // 添加更多散点数据
      ],
      tooltipVisible: false,
      tooltipData: {},
    };
  },
  mounted() {
    this.initScatterChart();
  },
  methods: {
    initScatterChart() {
      const scatterChart = echarts.init(this.$refs.scatterChart);
      // const lineContainer = this.$refs.lineContainer;

      const option = {
        tooltip: {
          show: false,
        },
        xAxis: {
          type: 'value', // 设置 x 轴类型为数值
        },
        yAxis: {
          type: 'value', // 设置 y 轴类型为数值
        },
        series: [
          {
            type: 'scatter',
            data: this.scatterData,
            symbolSize: 10,
            emphasis: {
              label: {
                show: true,
                position: 'top',
              },
            },
          },
        ],
      };

      scatterChart.setOption(option);

      scatterChart.getZr().on('mouseover', event => {
        this.updateLine(1400, 400,event.offsetX,  event.offsetY, );
      });
      scatterChart.getZr().on('mouseout', () => {
        this.handlePointMouseOut();
      });
    },
 
    handlePointMouseOut() {
      this.tooltipVisible = false;
      this.tooltipData = {};
      this.clearLine();
    },
    updateTooltipPosition() {
      const tooltipBox = this.$refs.tooltipBox;
      tooltipBox.style.left = '10px';
      tooltipBox.style.bottom = '10px';
    },
    getScatterPoint(x, y) {
      const scatterChart = this.$refs.scatterChart;
      const coord = scatterChart.convertToPixel('grid', [x, y]);
      return [coord[0], coord[1]];
    },
    updateLine(x1, y1, x2, y2) {
      console.log(x1,y1,x2,y2);
      const lineContainer = this.$refs.lineContainer;
      const curve = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      const controlPointX = (x1 + x2) / 2;
      const controlPointY = y1 - (y1 - y2) * 0.8;
      const path = `M${x1},${y1} Q${controlPointX},${controlPointY} ${x2},${y2}`;
      console.log('path','path');
      curve.setAttribute('d', path);
      curve.setAttribute('stroke', 'black');
      curve.setAttribute('fill', 'none');
      curve.setAttribute('stroke-width', '1');
      console.log(curve,'curve');
      lineContainer.appendChild(curve);
    },
    clearLine() {
      const lineContainer = this.$refs.lineContainer;
      lineContainer.innerHTML = '';
    },
  },
};
</script>

<style>
.scatter-container {
  position: relative;
  width: 100%;
  height: 500px;
}

.scatter-chart {
  width: 50%;
  height: 100%;
}

.tooltip-box {
  position: absolute;
  /* display: none; */
  background-color: #fff;
  width: 100px;
  height: 300px;
  left: 1400px;
  top: 200px;
  padding: 10px;
  border: 1px solid #000;
}

.line-container {
  position: absolute;
  top: 0;
  left:0;
  width: 100%;
  height: 100%;
  z-index: 222;
  pointer-events:none
}
</style>

this.updateLine(1400, 400,event.offsetX, event.offsetY, ); 1400 和400 是提示框位置 const controlPointY = y1 - (y1 - y2) * 0.8; 0.8为弧度