效果如上
html部分
<svg width="500px" height="500px" viewBox="0 0 400 400">
<!-- 绘制连线 -->
<template v-for="(point, index) in points">
<line :x1="point.x" :y1="point.y" :x2="index - 1 > 0 || index - 1 == 0 ? points[index - 1].x : point.x"
:y2="index - 1 > 0 || index - 1 == 0 ? points[index - 1].y : point.y" stroke="#1677ee" stroke-width="4"
key="index" />
<circle :cx="point.x" :cy="point.y" r="8" :fill="point.pointColor" key="index"
@click="getSiteDetails(point)" v-if="point.siteType != 'end'" />
<text :x="point.x" :y="point.y" fill="#fff" text-anchor="top" v-if="point.siteType != 'end'">{{ index + 1
}}</text>
<image xlink:href="../../../../assets/img/robot.png" height="25px" width="25px" :x="robotPos"
:y="robotPosY"></image>
</template>
</svg>
重点解释一下:
1.svg中的:width、height是整画布的大小;viewBox是视野的值(个人这么理解,可以通过改变其中的值越大 整个svg中的内容越小反之亦然)
2.这个图中的线段和圆形都是svg中的line和circle,根据后台中返回的数据实时生成的,所有使用了template遍历数据
3.其中的层级关系 谁在后面谁的层级越高(目前的文字越高)
4.其中引入的图片 路径需要上述的xlink:href引入
5.想要文字在圆形中居中可以设置 text-anchor="middle" alignment-baseline="middle"这俩个属性
<text x="200" y="200" text-anchor="middle" alignment-baseline="middle" fill="black" font-size="16px">
Your Text Here
</text>
回到那个页面中的js部分:其中这里是使用websocket实时发心跳,updateWorkStatus里就是反馈的实时数据
难点就是在于那个坡度的地方,需要沿着坡度去走,那么图片的y轴距离如何得出就是一个问题
(robotPos ,robotPosY)
整体的思路下面是实现方式:
//图片的实时状态
updateWorkStatus(v) {
this.robotPos = v.pos * 10
this.robotState = v.state
this.robotDir = v.dir
if (this.robotPos > this.upOpint.x && this.robotPos < this.downOpint.x) {
let lineLength = this.calculateHypotenuse((this.downOpint.x - this.upOpint.x), (this.upOpint.y - this.downOpint.y)) / (this.robotPos - this.upOpint.x)
this.robotPosY = 200 - (this.downOpint.y / lineLength) * 4
} else if (this.robotPos < this.upOpint.x) {
this.robotPosY = 200
} else if (this.robotPos > this.downOpint.x || this.robotPos == this.downOpint.x) {
this.robotPosY = 100
}
//机器人路过的点没有异常时候点变成绿色
this.points.forEach(item => {
//机器人的方向去判断
if (this.robotDir == 1) {
if (this.robotPos > item.pos * 10 || this.robotPos == item.pos * 10) {
item.pointColor = '#23A459'
}
} else if (this.robotDir == 2) {
if (this.robotPos < item.pos * 10) {
item.pointColor = '#23A459'
}
}
})
},
//a直角边a的长度 b直角边b的长度
calculateHypotenuse(a, b) {
var c = Math.sqrt(a * a + b * b);
return c;
},
站点折线数据加工:
// 获取站点初始化
setStaionList() {
if (this.uniqueid) {
initializeSiteList(this.uniqueid).then(res => {
let data = res.data.data
data.forEach(item => {
if (item.siteType == 'down') {
item.x = item.pos * 10
item.y = 100
item.pointColor = '#1677ee'
this.downOpint = {
x: item.pos * 10,
y: 100
}
} else if (item.siteType == 'end') {
item.x = item.pos * 10
item.y = 100
item.pointColor = '#1677ee'
} else if (item.siteType == 'up') {
item.x = item.pos * 10
item.y = 200
item.pointColor = '#1677ee'
this.upOpint = {
x: item.pos * 10,
y: 200
}
} else {
item.x = item.pos * 10
item.y = 200
item.pointColor = '#1677ee'
this.robotPosY = 200
}
})
this.points = data
})
}
},