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>