当前位置:首页 > VUE

vue实现动态飞线

2026-02-23 19:54:39VUE

Vue 实现动态飞线的方法

动态飞线效果常用于数据可视化场景,例如地图上的连线动画。以下是几种实现方式:

使用 SVG 和 Vue 实现基础飞线

<template>
  <svg width="500" height="300">
    <path 
      :d="pathData" 
      fill="none" 
      stroke="#1890ff" 
      stroke-width="2"
    />
    <circle 
      :cx="currentX" 
      :cy="currentY" 
      r="5" 
      fill="#f5222d"
    />
  </svg>
</template>

<script>
export default {
  data() {
    return {
      start: { x: 50, y: 50 },
      end: { x: 450, y: 250 },
      progress: 0
    }
  },
  computed: {
    pathData() {
      const controlX = (this.start.x + this.end.x) / 2;
      const controlY = (this.start.y + this.end.y) / 2 + 100;
      return `M${this.start.x},${this.start.y} Q${controlX},${controlY} ${this.end.x},${this.end.y}`;
    },
    currentX() {
      const t = this.progress;
      return (1-t)*(1-t)*this.start.x + 2*(1-t)*t*((this.start.x+this.end.x)/2) + t*t*this.end.x;
    },
    currentY() {
      const t = this.progress;
      return (1-t)*(1-t)*this.start.y + 2*(1-t)*t*((this.start.y+this.end.y)/2+100) + t*t*this.end.y;
    }
  },
  mounted() {
    this.animate();
  },
  methods: {
    animate() {
      const duration = 2000;
      const startTime = Date.now();

      const update = () => {
        const elapsed = Date.now() - startTime;
        this.progress = Math.min(elapsed / duration, 1);

        if (this.progress < 1) {
          requestAnimationFrame(update);
        } else {
          this.progress = 0;
          setTimeout(this.animate, 500);
        }
      };

      requestAnimationFrame(update);
    }
  }
}
</script>

使用第三方库实现高级效果

  1. ECharts + Vue-ECharts

安装依赖:

npm install echarts vue-echarts

实现代码:

<template>
  <v-chart 
    :option="option" 
    :init-options="initOptions" 
    autoresize
  />
</template>

<script>
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { LinesChart } from 'echarts/charts';
import {
  GridComponent,
  GeoComponent,
  TooltipComponent
} from 'echarts/components';
import VChart from 'vue-echarts';

use([
  CanvasRenderer,
  LinesChart,
  GridComponent,
  GeoComponent,
  TooltipComponent
]);

export default {
  components: { VChart },
  data() {
    return {
      initOptions: { renderer: 'canvas' },
      option: {
        series: [{
          type: 'lines',
          coordinateSystem: 'geo',
          polyline: true,
          data: [{
            coords: [
              [116.405285, 39.904989], // 北京
              [121.4747, 31.2304]     // 上海
            ],
            lineStyle: {
              color: '#a6c84c',
              width: 2,
              curveness: 0.2
            },
            effect: {
              show: true,
              period: 6,
              trailLength: 0.7,
              color: '#fff',
              symbolSize: 3
            }
          }]
        }]
      }
    }
  }
}
</script>

使用 D3.js 实现自定义飞线

<template>
  <div ref="chartContainer"></div>
</template>

<script>
import * as d3 from 'd3';

export default {
  mounted() {
    this.initChart();
  },
  methods: {
    initChart() {
      const width = 600;
      const height = 400;
      const svg = d3.select(this.$refs.chartContainer)
        .append('svg')
        .attr('width', width)
        .attr('height', height);

      const points = [
        { x: 100, y: 100 },
        { x: 500, y: 300 }
      ];

      const lineGenerator = d3.line()
        .curve(d3.curveBasis);

      const path = svg.append('path')
        .datum(points)
        .attr('d', lineGenerator)
        .attr('fill', 'none')
        .attr('stroke', 'steelblue')
        .attr('stroke-width', 2);

      const pathLength = path.node().getTotalLength();

      svg.append('circle')
        .attr('r', 5)
        .attr('fill', 'red')
        .attr('transform', `translate(${points[0].x},${points[0].y})`);

      svg.append('circle')
        .attr('r', 5)
        .attr('fill', 'red')
        .attr('transform', `translate(${points[1].x},${points[1].y})`);

      const animate = () => {
        svg.selectAll('.moving-circle').remove();

        svg.append('circle')
          .attr('class', 'moving-circle')
          .attr('r', 5)
          .attr('fill', 'orange')
          .transition()
          .duration(2000)
          .attrTween('transform', function() {
            return function(t) {
              const point = path.node().getPointAtLength(t * pathLength);
              return `translate(${point.x},${point.y})`;
            };
          })
          .on('end', animate);
      };

      animate();
    }
  }
}
</script>

性能优化建议

  1. 对于大量飞线动画,考虑使用 WebGL 方案如 Three.js
  2. 使用 requestAnimationFrame 替代 setTimeout 实现动画
  3. 对静态元素使用 CSS transform 加速渲染
  4. 对不再需要的 DOM 元素及时清理

以上方案可根据具体需求选择,SVG 方案适合简单场景,ECharts 提供开箱即用的解决方案,D3.js 则提供最大灵活性。

vue实现动态飞线

标签: 动态vue
分享给朋友:

相关文章

vue实现弹窗

vue实现弹窗

Vue 实现弹窗的常见方法 使用组件化方式封装弹窗 创建一个独立的弹窗组件(如 Modal.vue),通过 v-if 或 v-show 控制显示隐藏: <template> <…

vue 实现toast

vue 实现toast

vue 实现 toast 的方法 在 Vue 中实现 Toast 提示功能可以通过多种方式,以下是几种常见的实现方法: 使用第三方库 Vue 生态中有许多成熟的 Toast 库,例如 vue-toa…

分页实现vue

分页实现vue

分页实现(Vue) 在Vue中实现分页功能通常需要结合前端分页逻辑和后端API支持。以下是两种常见的实现方式: 前端分页实现 适用于数据量较小的情况,直接在客户端完成分页逻辑。 <tem…

vue实现ajax

vue实现ajax

Vue 中实现 AJAX 的几种方法 在 Vue 中实现 AJAX 请求可以通过原生 JavaScript 的 XMLHttpRequest、第三方库如 axios 或 fetch API 来完成。以…

vue实现tree

vue实现tree

Vue 实现 Tree 组件 使用 Vue 实现 Tree 组件可以通过递归组件的方式来实现层级结构展示。以下是一个完整的实现方法: 基础递归组件实现 创建 Tree 组件文件 Tree.vue,使…

实现vue cli

实现vue cli

安装 Vue CLI 确保系统中已安装 Node.js(版本建议 12.x 或更高)。通过 npm 全局安装 Vue CLI: npm install -g @vue/cli 安装完成后验证版本:…