所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

Vue3 Composition API与SVG.js深度整合方案

简介

SVG.js 是一个轻量级的 JavaScript 库,用于创建和操作 SVG 图形。本文介绍如何在 Vue3 项目中使用 SVG.js。

安装

npm install @svgdotjs/svg.js

基础使用

1. Vue 组件中初始化 SVG.js

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

<script setup>
import { ref, onMounted } from "vue";
import { SVG } from "@svgdotjs/svg.js";

const svgContainer = ref(null);

onMounted(() => {
  const draw = SVG().addTo(svgContainer.value).size(300, 300);

  // 绘制一个红色矩形
  draw.rect(100, 100).fill("#f06");
});
</script>

核心功能

1. 基本图形绘制

SVG.js 支持多种基本图形:

  • 矩形 .rect(width, height)
  • 圆形 .circle(radius)
  • 椭圆 .ellipse(width, height)
  • 直线 .line(x1, y1, x2, y2)
  • 多边形 .polygon(points)
  • 折线 .polyline(points)

2. 样式设置

// 设置填充和描边
draw.rect(100, 100)
  .fill('#f06')
  .stroke({ width: 2, color: '#333' })
  .radius(10) // 圆角

### 3. 动画效果

SVG.js内置了强大的动画功能:

```javascript
// 简单动画
draw.rect(100, 100)
  .animate(1000) // 1秒动画
  .move(100, 50)
  .rotate(45)
  .fill('#0f9')

// 链式动画
draw.circle(50)
  .animate(500).move(100, 100)
  .animate(500).move(200, 100)
  .animate(500).move(200, 200)
  .animate(500).move(100, 200)
  .loop() // 循环播放

4. 事件处理

const rect = draw.rect(100, 100).fill("#f06");

// 添加点击事件
rect.on("click", (event) => {
  console.log("矩形被点击", event);
  rect.fill("#0f9");
});

// 添加鼠标悬停事件
rect.on("mouseover", () => {
  rect.animate().fill("#f90");
});
rect.on("mouseout", () => {
  rect.animate().fill("#f06");
});

5. 组合与复用

// 创建可复用的符号
const symbol = draw.symbol();
symbol.rect(50, 50).fill("#f06");
symbol.circle(25).center(25, 25).fill("#fff");

// 使用符号
draw.use(symbol).move(10, 10);
draw.use(symbol).move(70, 10);

6. 与 Vue 响应式数据结合

<template>
  <div ref="svgContainer"></div>
  <input v-model.number="size" type="range" min="50" max="200" />
</template>

<script setup>
import { ref, watch, onMounted } from "vue";
import { SVG } from "@svgdotjs/svg.js";

const svgContainer = ref(null);
const size = ref(100);
const rect = ref(null);

onMounted(() => {
  const draw = SVG().addTo(svgContainer.value).size(300, 300);
  rect.value = draw.rect(size.value, size.value).fill("#f06");
});

watch(size, (newSize) => {
  rect.value?.size(newSize, newSize);
});
</script>

高级主题

1. 性能优化

  1. 避免频繁重绘
  2. 使用remember()缓存元素
  3. 合理使用group()分组元素

2. 与 Vue 组件库集成

可以创建可复用的 SVG 组件:

<!-- SvgRect.vue -->
<template>
  <div ref="svgContainer"></div>
</template>

<script setup>
import { ref, watch, onMounted } from "vue";
import { SVG } from "@svgdotjs/svg.js";

const props = defineProps({
  width: { type: Number, default: 100 },
  height: { type: Number, default: 100 },
  color: { type: String, default: "#f06" },
});

const svgContainer = ref(null);
const rect = ref(null);

onMounted(() => {
  const draw = SVG().addTo(svgContainer.value).size(300, 300);
  rect.value = draw.rect(props.width, props.height).fill(props.color);
});

watch(
  () => props.width,
  (w) => rect.value?.width(w)
);
watch(
  () => props.height,
  (h) => rect.value?.height(h)
);
watch(
  () => props.color,
  (c) => rect.value?.fill(c)
);
</script>

常见问题

  1. SVG 元素不显示:检查容器尺寸和 SVG 初始化是否正确
  2. 动画不流畅:减少同时运行的动画数量
  3. 事件不触发:确保元素有足够的可见区域

扩展应用场景

1. 数据可视化

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

<script setup>
import { ref, watch, onMounted } from "vue";
import { SVG } from "@svgdotjs/svg.js";

const props = defineProps({
  data: { type: Array, required: true },
});

const svgContainer = ref(null);
let draw = null;

onMounted(() => {
  draw = SVG().addTo(svgContainer.value).size(600, 400);
  updateChart();
});

watch(() => props.data, updateChart, { deep: true });

function updateChart() {
  draw?.clear();

  // 绘制柱状图
  const barWidth = 40;
  const maxValue = Math.max(...props.data);

  props.data.forEach((value, index) => {
    const height = (value / maxValue) * 300;
    draw
      .rect(barWidth, height)
      .move(index * (barWidth + 10), 400 - height)
      .fill(`hsl(${index * 30}, 70%, 50%)`)
      .on("mouseover", () => {
        draw
          .text(value.toString())
          .move(index * (barWidth + 10), 380 - height)
          .font({ size: 14 });
      });
  });
}
</script>

2. 交互式图形编辑器

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

<script setup>
import { ref, onMounted } from "vue";
import { SVG } from "@svgdotjs/svg.js";

const svgEditor = ref(null);
let selectedShape = null;

onMounted(() => {
  const draw = SVG().addTo(svgEditor.value).size(800, 600);

  // 创建可拖动矩形
  const rect = draw.rect(100, 100).move(50, 50).fill("#f06");
  rect.draggable();

  // 创建可拖动圆形
  const circle = draw.circle(80).move(200, 100).fill("#09f");
  circle.draggable();

  // 选择形状
  rect.on("click", () => selectShape(rect));
  circle.on("click", () => selectShape(circle));

  // 右键菜单
  draw.on("contextmenu", (event) => {
    event.preventDefault();
    if (selectedShape) {
      selectedShape.remove();
      selectedShape = null;
    }
  });
});

function selectShape(shape) {
  if (selectedShape) {
    selectedShape.stroke({ width: 0 });
  }
  selectedShape = shape;
  shape.stroke({ width: 2, color: "#000", dasharray: "5,5" });
}
</script>

3. SVG.js 插件集成

SVG.js 有许多强大的插件:

  1. svg.filter.js – 添加滤镜效果
import "@svgdotjs/svg.filter.js";
// 使用
rect.filterWith((add) => {
  add.gaussianBlur(5);
});
  1. svg.draggable.js – 增强拖拽功能
import "@svgdotjs/svg.draggable.js";
// 使用
circle.draggable();
  1. svg.panzoom.js – 添加平移缩放功能
import "@svgdotjs/svg.panzoom.js";
// 使用
draw.panZoom();

4. 性能优化进阶

  1. 使用 SVG Symbol 减少 DOM 节点
const symbol = draw.symbol();
symbol.rect(50, 50).fill("#f06");

// 复用Symbol
for (let i = 0; i < 100; i++) {
  draw.use(symbol).move(i * 60, 100);
}
  1. 批量操作减少重绘
// 不好的做法
for (let i = 0; i < 100; i++) {
  draw.circle(10).move(i * 15, 100);
}

// 好的做法 - 使用group
const group = draw.group();
for (let i = 0; i < 100; i++) {
  group.circle(10).move(i * 15, 100);
}
  1. 使用 requestAnimationFrame 优化动画
function animate() {
  shape
    .animate(16)
    .move(x, y)
    .after(() => {
      x += dx;
      y += dy;
      requestAnimationFrame(animate);
    });
}
animate();

高级调试技巧

1. 调试 SVG 元素

// 打印SVG元素的DOM节点
console.log(rect.node);

// 检查SVG元素的属性
console.log(rect.attr());

// 调试动画
rect.animate().during(function (pos) {
  console.log("当前动画进度:", pos);
});

2. 性能分析

// 测量渲染性能
console.time("render");
draw.rect(100, 100).fill("#f06");
console.timeEnd("render"); // 输出渲染耗时

// 使用Chrome DevTools分析内存使用
window._svgElements = []; // 用于内存分析
for (let i = 0; i < 1000; i++) {
  const el = draw.circle(10).move((i % 50) * 20, Math.floor(i / 50) * 20);
  window._svgElements.push(el);
}

总结

SVG.js 与 Vue3 结合可以创建丰富的交互式图形应用。通过组件化封装,可以实现高度复用的 SVG 图形组件。

原文链接:https://code.ifrontend.net/archives/978,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?