vue使用svg在图片上进行各种绘制
<template>
<div class="outer" ref="outerRef">
<div class="inner" ref="innerRef" :style="innerStyle">
<img ref="imgRef" :src="mapUrl" alt="地图加载中" @load="imageLoad" />
<svg ref="svgRef" :style="svgStyle">
<image
:href="robotPosition.url"
:width="robotPosition.width"
:height="robotPosition.height"
:x="robotPosition.x"
:y="robotPosition.y"
:style="{
// transform: robotPosition.transform,
// transformOrigin: robotPosition.transformOrigin,
}"
/>
<text x="100" y="100" fill="red">1231</text>
<g>
<circle
v-for="point in mapPointList"
:key="point.id"
:cx="point.x"
:cy="point.y"
r="4"
fill="red"
/>
</g>
</svg>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "HelloWorld",
data() {
return {
mapUrl:
"https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg",
robotPosition: {
// x: 449,
// y: 132,
// x: 116,
// y: 87,
x: 0,
y: 0,
url: require("@/assets/images/robot.png"),
// width: 16,
// height: 16,
width: 4.8,
height: 4.8,
transform: "rotate(33deg)", // 机器人朝向角度
transformOrigin: "center center",
},
mapPointList: [
{
id: "1",
x: 100,
y: 100,
},
{
id: "2",
x: 200,
y: 200,
},
],
imgoffsetX: 0,
imgoffsetY: 0,
scale: 1,
svgInfo: {
imageNaturalWidth: 1,
imageNaturalHeight: 1,
imageWidth: 1,
imageHeight: 1,
svgWidth: 1,
svgHeight: 1,
offsetX: 1,
offsetY: 1,
svgRate: 1,
scale: 1.5,
},
};
},
mounted() {
let aa = true;
let a = [];
this.$refs.outerRef.addEventListener("mousedown", (e) => {
e.stopPropagation();
e.preventDefault();
console.log(e);
aa = false;
a.x = e.clientX;
a.y = e.clientY;
});
this.$refs.outerRef.addEventListener("mousemove", (e) => {
if (!aa) {
let x = e.clientX - a.x;
let y = e.clientY - a.y;
this.imgoffsetX += x;
this.imgoffsetY += y;
a.x = e.clientX;
a.y = e.clientY;
}
});
this.$refs.outerRef.addEventListener("mouseup", (e) => {
aa = true;
// console.log(e);
});
this.$refs.outerRef.addEventListener("mousewheel", (e) => {
if (e) {
if (e.wheelDelta > 0) {
console.log("向上滚动");
this.zoomIn();
this.scale += 0.1;
}
if (e.wheelDelta < 0) {
console.log("向xia滚动");
this.zoomOut();
this.scale -= 0.1;
}
}
});
// 移动端
let isTouch = false; //是否为单触点
let isDoubleTouch = false; //是否为多触点
let start = []; //存放触点坐标
this.$refs.innerRef.addEventListener("touchstart", (e) => {
console.log(e);
aa = false;
if (e.touches.length >= 2) {
//判断是否有两个点在屏幕上
start = e.touches; //得到第一组两个点
isDoubleTouch = true;
} else {
isTouch = true;
a.x = e.touches[0].clientX;
a.y = e.touches[0].clientY;
}
});
this.$refs.innerRef.addEventListener("touchmove", (e) => {
if (!aa) {
if (e.touches.length >= 2 && isDoubleTouch) {
//判断是否有两个点在屏幕上
let now = e.touches; //得到第二组两个点
let scale =
getDistance(now[0], now[1]) / getDistance(start[0], start[1]); //得到缩放比例
this.scale += scale;
} else if (isTouch) {
let x = e.touches[0].clientX - a.x;
let y = e.touches[0].clientY - a.y;
that.imgoffsetX += x;
that.imgoffsetY += y;
a.x = e.touches[0].clientX;
a.y = e.touches[0].clientY;
}
}
});
this.$refs.innerRef.addEventListener("touchend", (e) => {
aa = true;
// console.log(e);
if (isDoubleTouch) {
zoomKey = false;
isDoubleTouch = false;
} else if (isTouch) {
isTouch = false;
}
});
},
computed: {
svgStyle() {
return {
width: this.svgInfo.svgWidth + "px",
height: this.svgInfo.svgHeight + "px",
left: this.svgInfo.offsetX + "px",
top: this.svgInfo.offsetY + "px",
};
},
innerStyle() {
return {
left: this.imgoffsetX + "px",
top: this.imgoffsetY + "px",
transform: `scale(${this.scale})`,
};
},
},
methods: {
zoomIn() {
this.svgInfo.scale += 0.1;
},
zoomOut() {
this.svgInfo.scale -= 0.1;
},
moveRight() {
this.svgInfo.offsetX += 10;
},
moveLeft() {
this.svgInfo.offsetX -= 10;
},
moveUp() {
this.svgInfo.offsetY -= 10;
},
moveDown() {
this.svgInfo.offsetY += 10;
},
imageLoad() {
const imgRef = this.$refs.imgRef;
this.svgInfo = {
imageNaturalWidth: imgRef.naturalWidth,
imageNaturalHeight: imgRef.naturalHeight,
imageWidth: imgRef.clientWidth,
imageHeight: imgRef.clientHeight,
svgWidth: imgRef.clientWidth,
svgHeight: imgRef.clientHeight,
offsetX: 0,
offsetY: 0,
svgRate: 1,
};
let svgRate = this.svgInfo.imageWidth / this.svgInfo.imageHeight;
let imageNaturalRate =
this.svgInfo.imageNaturalWidth / this.svgInfo.imageNaturalHeight;
console.log(svgRate, imageNaturalRate);
if (svgRate > imageNaturalRate) {
this.svgInfo.svgRate =
this.svgInfo.imageHeight / this.svgInfo.imageNaturalHeight;
this.svgInfo.svgHeight = this.svgInfo.imageHeight;
this.svgInfo.svgWidth = this.svgInfo.imageHeight * imageNaturalRate;
} else {
this.svgInfo.svgRate =
this.svgInfo.imageWidth / this.svgInfo.imageNaturalWidth;
this.svgInfo.svgWidth = this.svgInfo.imageWidth;
this.svgInfo.svgHeight = this.svgInfo.imageWidth / imageNaturalRate;
}
this.svgInfo.offsetX =
(this.svgInfo.imageWidth - this.svgInfo.svgWidth) / 2;
this.svgInfo.offsetY =
(this.svgInfo.imageHeight - this.svgInfo.svgHeight) / 2;
this.robotPosition.width = 16 * this.svgInfo.svgRate;
this.robotPosition.height = 16 * this.svgInfo.svgRate;
this.robotPosition.x = this.svgInfo.svgRate * 680;
this.robotPosition.y =
this.svgInfo.svgHeight - this.svgInfo.svgRate * 167;
},
},
};
</script>
<style lang="scss" scoped>
.outer {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
padding: 50px;
box-sizing: border-box;
.inner {
width: 100%;
height: 100%;
position: relative;
img {
width: 100%;
height: 100%;
object-fit: contain;
position: absolute;
left: 0;
top: 0;
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
}
}
</style>