只用到img标签的平面图和svg标签的点位,我项目用的是拖动事件打点,vue的@dragstart 和@drop="ondrop"事件配合,点击的话你们自己修改接收事件的方式即可
20230609-150853
图示:
鼠标悬浮图标显示弹出层
子组件
<template>
<div class="clickMap">
<div
ref="clickMap"
@mousewheel="mousewheelImg"
:style="{
transform: 'scale(' + num + ')',
position: 'relative',
width: '100%',
height: '100%',
}"
@mousedown="moveMouse"
@click="getOffect"
>
<div v-for="(item, index) in pointPosition" :key="index">
<svg-icon
@click="iconClick(item)"
slot="reference"
v-if="item.iconUrl && !popover"
:style="{
position: 'absolute',
left: item.leftName + 'px',
top: item.topName + 'px',
fontSize: item.fontSize + 'px',
color: item.iconColor,
}"
:icon-class="item.iconUrl"
/>
<el-popover
:ref="'popoverSH' + item.id"
v-else
popper-class="popover"
placement="right-start"
width="200"
trigger="hover"
>
<div>
<el-row>
<el-col> <span>设备名称:</span> {{ item.deviceName }}</el-col>
<el-col> <span>设备编号:</span> {{ item.id }} </el-col>
<el-col>
<span>设备类型:</span> {{ item.deviceTypeName }}</el-col
>
<el-col
><span>安装位置:</span> {{ item.installationLocation }}</el-col
>
<el-col
><span>状态:</span>
<b style="color: red" v-if="item.useStatus == 1">未激活</b
><b style="color: #0ecc67" v-if="item.useStatus == 2">在线</b
><b style="color: red" v-if="item.useStatus == 3"
>离线</b
></el-col
>
<p style="text-align: right">
<span @click="detailEvent(item)" class="xiaoshou"
>详情<i class="el-icon-d-arrow-right"></i
></span>
</p>
</el-row>
</div>
//svg-icon是ruoyi框架的组件,你们没有的自行替换
<svg-icon
slot="reference"
v-if="item.iconUrl"
:style="{
position: 'absolute',
left: item.leftName + 'px',
top: item.topName + 'px',
fontSize: item.fontSize + 'px',
color: item.iconColor,
}"
:icon-class="item.iconUrl"
/>
</el-popover>
</div>
<img
style="width: 100%; height: 100%; pointer-events: none"
:src="detailTable.url"
alt=""
@mousedown="isTrue ? null : move"
/>
</div>
</div>
</template>
<script>
export default {
data() {
return {
width: "",
height: "",
left: "",
top: "",
biaozhuHeight: 0,
biaozhuWidth: 0,
biaozhuTop: 0,
biaozhuLeft: 0,
moveTop: 0,
moveLeft: 0,
};
},
props: {
detailTable: Object, //包含图片的对象
isTrue: Boolean, //是否可以拖动
pointPosition: Array, //点位坐标数组
drag: Boolean,
num: {
//放大缩小倍速默认1
type: Number,
default: 1,
},
popover: {
//是否显示弹出层
type: Boolean,
default: false,
},
},
methods: {
// 放大缩小
mousewheelImg(e) {
if (e.deltaY > 0) {
if (this.num < 0.3) return;
this.$emit("zoom", "缩小");
} else {
this.$emit("zoom", "放大");
}
},
getOffect(e) {
document.onmouseup = null;
},
// 拖动
moveMouse(e) {
let odiv = e.target; //获取目标元素
//算出鼠标相对元素的位置
let disX = e.clientX - odiv.offsetLeft;
let disY = e.clientY - odiv.offsetTop;
// console.log(disX, disY);
if (this.isTrue) {
// 拖动
document.onmousemove = (e) => {
//鼠标按下并移动的事件
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
//绑定元素位置到positionX和positionY上面
this.positionX = top;
this.positionY = left;
//移动当前元素
odiv.style.left = left + "px";
odiv.style.top = top + "px";
};
document.onmouseup = (e) => {
document.onmousemove = null;
document.onmouseup = null;
};
}
},
detailEvent(item) {
this.$refs["popoverSH" + item.id][0].doClose(); //点击之后隐藏面板
this.$emit("detailEvent", item);
},
// 打点事件
ondrop(e) {
let odiv = e.target; //获取目标元素
//算出鼠标相对元素的位置
let disX = e.clientX - odiv.offsetLeft;
let disY = e.clientY - odiv.offsetTop;
console.log(disX, disY);
if (this.isTrue) {
// 拖动
document.onmousemove = (e) => {
//鼠标按下并移动的事件
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
//绑定元素位置到positionX和positionY上面
this.positionX = top;
this.positionY = left;
//移动当前元素
odiv.style.left = left + "px";
odiv.style.top = top + "px";
};
document.onmouseup = (e) => {
document.onmousemove = null;
document.onmouseup = null;
};
} else {
let left =
disX -
odiv.getBoundingClientRect().x +
Number(this.$refs.clickMap.style.left.replace(/px/, "") - 5);
let top =
disY -
odiv.getBoundingClientRect().y +
Number(this.$refs.clickMap.style.top.replace(/px/, "") - 5);
let data = {
leftName: left / this.num,
topName: top / this.num,
// iconName: "sensor", //没有传图标的话默认传感器图标
};
this.$emit("addBitmap", data);
this.biaozhuWidth = 0;
this.biaozhuHeight = 0;
this.biaozhuLeft = 0;
this.biaozhuTop = 0;
document.onmousemove = null;
document.onmouseup = null;
}
},
//点击图标事件
iconClick(data) {
this.$emit("iconClick", data);
},
},
destroyed() {
document.mousewheelImg = null;
},
};
</script>
<style lang="scss">
.popover {
background: #678295;
border: 2px solid #0095ff;
color: #ffffff;
font-size: 16px;
.xiaoshou {
cursor: pointer; /*鼠标悬停变小手*/
}
.el-col {
line-height: 32px;
span {
font-weight: bold;
}
}
}
.clickMap {
width: 400px;
height: 300px;
// background: red;
margin: 0 auto;
position: relative;
// border: 1px solid #999999;
.r_b {
position: absolute;
right: 0;
bottom: 0;
width: 20px;
height: 20px;
// background: red;
}
.r_b:hover {
cursor: se-resize;
}
}
.popover-top {
height: 60px;
img {
width: 50px;
height: 50px;
}
span {
float: right;
}
}
.popover-content,
.popover-footer {
border-top: 1px solid #f1f1f1;
span {
margin-right: 5px;
font-weight: bold;
}
.el-col {
line-height: 22px;
}
}
</style>
父组件
<div class="maList" ref="maList" @dragover.prevent @drop="ondrop">
<click-map
@addBitmap="addBitmap"
:detailTable="detailTable"
:pointPosition="mapTable"
:isTrue="isTrue"
:num="num"
@zoom="zoom"
v-if="detailTable.url"
:drag="true"
ref="clickMap"
@iconClick="iconClick"
/>
</div>
data() {
return {
/*-mapTable: [[{leftName:11,topName:11,fontSize:11,iconColor:'#999999',iconUrl:图标的地址}]]---*/
/*--detailTable里面要有url--*/
/*--------------------------------*/
detailTable: {}, //图片
isTrue: true, //是否允许拖动
checkedTable: {}, //保存拖动要打点设备的参数
mapTable: [], //打点的坐标数组
num: 1, //放大缩小倍数
/*--------------------------------*/
};
},
// 点击图标滚动到某一行事件
iconClick(data) {
this.radioType = 1;
this.$nextTick(function () {
this.deviceList.forEach((element, index) => {
if (element.id == data.id) {
console.log(index);
//滚动到某一行加高亮
this.$refs.deviceList.scrollToRow(this.deviceList[index]);
this.$refs.deviceList.setCurrentRow(this.deviceList[index]);
}
});
});
},
// 打点之后返回的坐标系数
addBitmap(data) {
this.checkedTable.spaceId = this.$refs.tree.getCurrentNode().id;
this.checkedTable.topName = data.topName;
this.checkedTable.leftName = data.leftName;
console.log(this.checkedTable);
uploadDevice(this.checkedTable).then((res) => {
this.isTrue = !this.isTrue;
this.$message({
message: "打点成功",
type: "success",
});
this.getDevice(); //更新设备列表
this.equipmentOverviewEvent() //更新设备总览
deviceList(this.mapForm).then((res) => {
this.mapTable = res.rows;
this.total = res.total;
});
});
},
// 放大缩小
zoom(value) {
if (value == "放大") {
this.num += 0.1;
} else {
this.num -= 0.1;
}
},
dragstart(data) {
this.checkedTable = data;
this.isTrue = false;
console.log("长按拖动中");
},
ondrop(e) {
console.log("长按松开了");
this.$refs.clickMap.ondrop(e);
},
公司需要拖动打点,dragstart和ondrop方法就是vue的拖动松开配合使用的事件,不懂的可以自行百度,可以简单的改为点击打点也行,自行修改
后续更新一点小demo给你们参考
20230627-171901
源码下载地址:
https://gitee.com/coderjiejie/vue2_map