ZRender开发
开发文档:https://ecomfe.github.io/zrender-doc/public/
<!-- eslint-disable no-undef -->
<template>
<div class="config-page">
<div class="header">
<el-button @click="handleAdd">撒点</el-button>
<el-button @click="clearPoints">清除撒点</el-button>
<el-button @click="drawLines">生产轨迹</el-button>
<el-button @click="clearLines">清除轨迹</el-button>
</div>
<div class="content">
<!-- 阻止默认的鼠标右键事件 -->
<div id="container" @contextmenu.prevent></div>
<!-- 鼠标悬浮提示 -->
<div v-show="titleTip" id="tip">{{ titleTip }}</div>
</div>
</div>
</template>
<script>
import * as zrender from 'zrender/dist/zrender'
let container, zr
export default {
data() {
return {
group: null,
pointGroup: null,
lineGroup: null,
bgImg: new URL('../assets/images/1.jpg', import.meta.url).href,
isActive: false,
pointList: [],
pointListNormalization: [],
cameraIcon: new URL('../assets/images/camera_n.png', import.meta.url).href,
zrBgImg: null,
titleTip: '',
titleElement: null,
index: 1,
positionImg: new URL('../assets/images/position.png',import.meta.url).href,
posZrImage: null,
points: [
[400, 400],
[450, 450],
[450, 500],
[500, 500],
],
currentIndex: 1,
}
},
mounted() {
this.init()
this.titleElement = document.getElementById('tip')
},
methods: {
// zr => group => zrBgImg + pointGroup + lineGroup
init() {
container = document.getElementById('container')
// 初始化 ZRender
zr = zrender.init(container)
// 创建组
this.group = new zrender.Group()
zr.add(this.group)
this.zrBgImg = new zrender.Image({
style: {
image: this.bgImg,
x: 0,
y: 0,
width: container.clientWidth,
height: container.clientHeight
},
z: 1,
cursor: 'unset',
})
this.group.add(this.zrBgImg)
this.zrBgImg.on('click', (data) => {
const { offsetX, offsetY } = data
this.isActive && this.addMarker(offsetX, offsetY)
})
// 创建组:用于存放监控点
this.pointGroup = new zrender.Group()
this.group.add(this.pointGroup)
// 创建组:用于存放轨迹线
this.lineGroup = new zrender.Group()
this.group.add(this.lineGroup)
this.drawLines1()
this.drawLines2()
},
handleAdd() {
this.changeStatus(true)
},
// 添加标记
addMarker(x, y) {
const marker = new zrender.Image({
style: {
image: this.cameraIcon,
x: x - 14,
y: y - 14,
width: 28,
height: 28,
},
z: 3,
cursor: 'pointer',
id: `id_${this.index}`,
name: `camera_${this.index}`
})
this.pointGroup.add(marker)
this.pointListNormalization.push([x / container.clientWidth, y / container.clientHeight])
this.pointList.push([x, y])
this.index++
marker.on('mouseover', (data) => {
// 添加鼠标悬浮提示
const { target: { name, style: { x, y, width, height } } } = data
this.titleTip = name
this.titleElement.style.left = `${x + width}px`
this.titleElement.style.top = `${y + height}px`
})
marker.on('mouseout', () => {
// 隐藏鼠标悬浮提示
this.titleTip = ''
})
marker.on('click', (data) => {
console.log(data, data.target.id)
})
marker.on('contextmenu', (data) => {
this.$confirm('是否确定删除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
.then(() => {
const { target } = data
this.pointGroup.remove(target)
})
.catch(() => {
this.$message({
type: 'success',
message: '已取消删除!',
})
})
})
this.$nextTick(() => {
this.changeStatus(false)
})
},
drawLines() {
console.log(this.pointListNormalization)
// 多边形
const polyline1 = new zrender.Polyline({
shape: {
points: this.pointList,
smooth: 0
},
style: {
lineWidth: 5,
stroke: '#F7B71F',
},
z: 2,
})
this.lineGroup.add(polyline1)
const polyline2 = new zrender.Polyline({
shape: {
points: this.pointList,
smooth: 0
},
style: {
lineDash: [10, 10],
stroke: '#ffffff', // 描边样式
lineWidth: 2,
},
z: 2,
})
this.lineGroup.add(polyline2)
polyline2
.animate('style', true)
.when(1000, {
lineDashOffset: -20,
})
.start()
},
drawLines1() {
let polyline = new zrender.Polyline({
shape: {
points: [
[100, 100],
[150, 150],
[150, 200],
[300, 300],
],
smooth: 0,
},
style: {
lineDash: [8, 2],
stroke: 'rgba(0,255,253,0.7)', // 描边样式
lineWidth: 1,
shadowBlur: 10,
shadowColor: 'rgba(13,253,240,0.78)',
},
z: 22,
})
this.lineGroup.add(polyline)
let circle = new zrender.Circle({
shape: {
cx: 100,
cy: 100,
r: 2,
},
style: {
fill: '#ffffff',
stroke: '#ffffff',
shadowBlur: 8,
shadowColor: 'rgba(255, 255, 255, 0.5)',
},
z: 22,
})
this.lineGroup.add(circle)
circle
.animate('shape', true)
.when(1000, {
cx: 150,
cy: 150,
})
.when(2000, {
cx: 150,
cy: 200,
})
.when(3000, {
cx: 300,
cy: 300,
})
.start()
},
drawLines2 () {
// 多边形
const polyline1 = new zrender.Polyline({
shape: {
points: this.points,
smooth: 0
},
style: {
lineWidth: 5,
stroke: '#F7B71F',
},
z: 2,
})
this.lineGroup.add(polyline1)
this.posZrImage = new zrender.Image({
style: {
image: this.positionImg,
x: this.points[0][0] - 16,
y: this.points[0][1] - 32,
width: 32,
height: 32,
},
z: 3,
})
this.lineGroup.add(this.posZrImage)
this.animate()
},
// 定位图标沿着轨迹运动
animate() {
this.posZrImage.animate('style', false).when(2000, {
x: this.points[this.currentIndex][0] - 16,
y: this.points[this.currentIndex][1] - 32,
}).start().done(() => {
this.currentIndex++
if (this.currentIndex < this.points.length) {
this.animate()
}
})
},
clearPoints() {
this.pointGroup.removeAll()
// 未知:加上后,removeAll才生效
this.changeStatus(false)
this.pointList = []
this.pointListNormalization = []
},
clearLines() {
this.lineGroup.removeAll()
// 未知:加上后,removeAll才生效
this.changeStatus(false)
},
changeStatus(val) {
this.isActive = val
this.zrBgImg?.attr({
cursor: val ? 'pointer' : 'unset',
})
}
}
}
</script>
<style lang="scss">
.config-page {
width: 100%;
height: 100%;
padding: 20px;
.header {
height: 40px;
display: flex;
align-items: center;
}
.content {
width: 1366px;
height: 768px;
position: relative;
#container {
width: 100%;
height: 100%;
}
#tip {
position: absolute;
border: 1px solid #4d4d4d;
background-color: #fff;
padding: 4px;
z-index: 1;
}
}
}
</style>