<!-- MapFlyLine.vue -->
<template>
    <div class="flyline-container" ref="container">
      <canvas ref="canvas" class="flyline-canvas"></canvas>
    </div>
  </template>
  
  <script>
  export default {
    name: 'MapFlyLine',
    props: {
      // 地图实例（需要从父组件传递）
      mapData: {
        type: Object,
        required: true
      },
      // 飞线数据
      data: {
        type: Array,
        default: () => []
      },
      // 配置项
      config: {
        type: Object,
        default: () => ({})
      }
    },
    data() {
      return {
        ctx: null,
        animationFrame: null,
        defaultConfig: {
          color: '#4f99d3',
          lineWidth: 1,
          animationSpeed: 0.02,
          maxLength: 0.3,
          curvature: 0.3
        }
      }
    },
    computed: {
      mergedConfig() {
        return { ...this.defaultConfig, ...this.config }
      }
    },
    mounted() {
      this.initCanvas()
      this.startAnimation()
      window.addEventListener('resize', this.handleResize)
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.handleResize)
      cancelAnimationFrame(this.animationFrame)
    },
    watch: {
      data: {
        deep: true,
        handler() {
          this.drawLines()
        }
      }
    },
    methods: {
      initCanvas() {
        const canvas = this.$refs.canvas
        const container = this.$refs.container
        canvas.width = container.offsetWidth
        canvas.height = container.offsetHeight
        this.ctx = canvas.getContext('2d')
        this.ctx.globalCompositeOperation = 'lighter'
      },
  
      handleResize() {
        this.initCanvas()
        this.drawLines()
      },
  
      startAnimation() {
        const animate = () => {
          this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height)
          this.drawLines()
          this.animationFrame = requestAnimationFrame(animate)
        }
        animate()
      },
  
      drawLines() {
        if (!this.data.length) return
  
        this.data.forEach(line => {
          const from = this.mapInstance.convertToPixel(...line.from)
          const to = this.mapInstance.convertToPixel(...line.to)
          
          this.drawCurve(
            from,
            from,
            to,
            to,
            line.color || this.mergedConfig.color
          )
        })
      },
  
      drawCurve(x1, y1, x2, y2, color) {
        const ctx = this.ctx
        const cp = this.calculateControlPoint(x1, y1, x2, y2)
        
        // 飞线渐变效果
        const gradient = ctx.createLinearGradient(x1, y1, x2, y2)
        gradient.addColorStop(0, color)
        gradient.addColorStop(1, color + '00')
  
        ctx.beginPath()
        ctx.moveTo(x1, y1)
        ctx.quadraticCurveTo(cp.x, cp.y, x2, y2)
        
        // 创建虚线动画效果
        ctx.setLineDash([5, 3])
        ctx.lineDashOffset = -performance.now() * this.mergedConfig.animationSpeed
        
        ctx.strokeStyle = gradient
        ctx.lineWidth = this.mergedConfig.lineWidth
        ctx.stroke()
      },
  
      calculateControlPoint(x1, y1, x2, y2) {
        // 计算曲线控制点（贝塞尔曲线）
        const curvature = this.mergedConfig.curvature
        const dx = x2 - x1
        const dy = y2 - y1
        return {
          x: (x1 + x2) / 2 + dy * curvature,
          y: (y1 + y2) / 2 - dx * curvature
        }
      }
    }
  }
  </script>
  
  <style scoped>
  .flyline-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
  }
  
  .flyline-canvas {
    width: 100%;
    height: 100%;
  }
  </style>
  