封装svg图片展示及操作组件——svgComponent——js技能提升

template部分

js 复制代码
<template>
  <div class="canvas-wrapper" ref="canvasWrapper">
    <svg
        :viewBox="computedViewBox"
        ref="svgCanvas"
        xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        class="schematic-svg"
        @mousedown="startDrag"
        @mousemove="onDrag"
        @mouseup="endDrag"
        @wheel="onScroll"
        v-html="svgContent"
        preserveAspectRatio="xMinYMin meet"
    >
    </svg>
  </div>
</template>


this.klFile = "data:image/svg+xml;base64," + data[0].kl_svg
<svg-component v-if="klFile !== null" :svg-base64="klFile" view-box="0 0 2000 2000"></svg-component>

script部分

js 复制代码
<script>
export default {
  name:'SvgComponent',
  props: {
    svgBase64: {
      type: String,
      required: true
    },
    viewBox: {
      type: String,
      required: true
    },
  },
  data() {
    return {
      computedViewBox: this.viewBox, // 用于动态修改的 viewBox
      dragging: false,
      startX: 0,
      startY: 0,
      viewBoxX: 0,
      viewBoxY: 0,
      svgContent: "", // 存储解码后的 SVG 内容
    };
  },
  watch: {
    svgBase64() {
      // 响应 props 变化并重新渲染 SVG
      this.decodeSvgBase64();
    },
  },
  mounted() {
    this.decodeSvgBase64();
  },
  methods: {
    decodeSvgBase64() {
      // 解码 Base64 数据
      // 检查并移除可能存在的 Base64 数据头
      let base64String = this.svgBase64;
      const prefix = "data:image/svg+xml;base64,";

      if (base64String.startsWith(prefix)) {
        base64String = base64String.replace(prefix, "");
      }

      // 尝试解码 Base64 数据
      const decodedData = atob(base64String);

      this.svgContent = decodedData; // 将解码后的内容赋值给 svgContent
    },
    startDrag(event) {
      this.dragging = true;
      this.startX = event.clientX;
      this.startY = event.clientY;
    },
    onDrag(event) {
      if (this.dragging) {
        const dx = this.startX - event.clientX;
        const dy = this.startY - event.clientY;
        this.viewBoxX += dx;
        this.viewBoxY += dy;
        this.updateViewBox();
        this.startX = event.clientX;
        this.startY = event.clientY;
      }
    },
    endDrag() {
      this.dragging = false;
    },
    onScroll(event) {
      event.preventDefault();
      const zoomAmount = 1.1;
      const [x, y, w, h] = this.computedViewBox.split(" ").map(Number);

      // Zoom in or out
      if (event.deltaY < 0) {
        // Zoom in
        this.computedViewBox = `${x + w * (1 - 1 / zoomAmount) / 2} ${y + h * (1 - 1 / zoomAmount) / 2} ${w / zoomAmount} ${h / zoomAmount}`;
      } else {
        // Zoom out
        this.computedViewBox = `${x - w * (zoomAmount - 1) / 2} ${y - h * (zoomAmount - 1) / 2} ${w * zoomAmount} ${h * zoomAmount}`;
      }
    },
    updateViewBox() {
      const [x, y, w, h] = this.viewBox.split(" ").map(Number);
      this.computedViewBox = `${this.viewBoxX} ${this.viewBoxY} ${w} ${h}`;
    }
  },
};
</script>

css部分

css 复制代码
<style scoped>
.canvas-wrapper {
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  overflow: hidden;
}

.schematic-svg {
  width: 100%;
  height: 100%;
}
</style>
相关推荐
dialect_15 小时前
KMP算法
开发语言·c++·算法
jktantan16 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
总要学点什么16 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
前端精髓17 小时前
调用openrouter的免费API模型
java·前端·javascript
开开心心_Every18 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
chenbingjie_c18 小时前
C++ 多态完全指南:从虚函数重写到虚函数表原理
开发语言·c++
吴卫斌18 小时前
定投ETF实战指南(四):行业/主题ETF——定投的“进攻端“
开发语言·python·股票·量化
超级架构师19 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
叼烟扛炮20 小时前
Linux 学习笔记(四十三):网络编程进阶——自定义协议解决 TCP 粘包与守护进程
linux·开发语言·网络·笔记·tcp/ip
LMT流氓兔20 小时前
第五单元——第十六课:给书店助手加上网页界面
java·开发语言·jvm·人工智能·oracle·langchain·1024程序员节