首先 左边的线连接右边的线的话 都要准确找到双方的位置
所以我们通过getBoundingClientRect()方法去寻找
例:this.$refs[`${item.refs}`][0].getBoundingClientRect().left
例:this.$refs[`${item.refs}`][0].getBoundingClientRect().top
但是呢 如果你的canvas在屏幕的任意位置 直接用上面获取的话是不行的。获取的位置不是以canvas为基准获取的而是以屏幕的宽高。所以↓
this.$refs[`canvas`].getBoundingClientRect().left
this.$refs[`canvas`].getBoundingClientRect().top
思路是 首先要获取画布在屏幕的位置 在用获取每个div要连线的位置减去canvas在屏幕的位置
this.$refs[`${item.refs}`][0].getBoundingClientRect().left-windowLeft
this.$refs[`${item.refs}`][0].getBoundingClientRect().top-windowtop
这是解决了 目前div在画布的准确位置
当要连接的时候 首先还要知道单个连接多个 个单个连接单个的时候。如何去解决他们的哪个连接 哪个不连接。
首先当我们点击某个的时候应该就已经知道了要连接谁。所以当我们刚开始给每组数据都先添加一个自定义的ref的时候。在连接时就要把不需要连接的div去掉ref设置为空,把需要连接的div保留下来
deepClone(obj){ //拷贝
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
},
let list = this.deepClone(this.abnormalStage)
this.abnormalStage = list.map(e=>{
let index = this.linelianList.findIndex(es=>es == e.stageId )
if(index==-1){
e.refs = ""
}
return e
})
然后就是连接了。
把map之后的数据信生成一个数组,来存储要连接的坐标。
let guocuoXY = []
list.forEach(e=>{
if(e.refs != ''){
guocuoXY.push(
{
x:this.$refs[`${e.refs}`][0].getBoundingClientRect().left-windowLeft,
y:this.$refs[`${e.refs}`][0].getBoundingClientRect().top-windowtop,
}
)
}
})
然后在画线
guocuoXY.forEach(e=>{
//设置路径起点坐标
ctx.moveTo(div1Light,div1Top)
//定义中间点坐标1
ctx.lineTo((div1Light+e.x-220)/2,div1Top)
// //定义中间点坐标2
ctx.lineTo((div1Light+e.x-220)/2,e.y)
//定义中间点坐标3(这是最后一个中间点,也就是终点)
ctx.lineTo(e.x-size,e.y);
// let obj = guocuoXY[guocuoXY.length-1]
// console.log(obj)
var arrowX, arrowY;//箭头线终点坐标
var headlen = 10;//自定义箭头线的长度
var theta = 45;//自定义箭头线与直线的夹角,个人觉得45°刚刚好
var angle = Math.atan2(e.y - e.y, e.x+20 - e.x-size) * 180 / Math.PI;
var angle1 = (angle + theta) * Math.PI / 180;
var angle2 = (angle - theta) * Math.PI / 180;
var topX = headlen * Math.cos(angle1);
var topY = headlen * Math.sin(angle1);
var botX = headlen * Math.cos(angle2);
var botY = headlen * Math.sin(angle2);
arrowX = e.x-size + topX;
arrowY = e.y + topY;
//画上边箭头线
ctx.moveTo(arrowX, arrowY);
ctx.lineTo(e.x-size, e.y);
arrowX = e.x-size + botX;
arrowY = e.y + botY;
//画下边箭头线
ctx.lineTo(arrowX, arrowY);
})
后面再设置线的宽度
ctx.lineWidth = 2;
ctx.stroke();
//关闭绘制路径
ctx.closePath();
this.normalList = this.normalListliu
this.abnormalStage = this.abnormalStageliu
整体代码如下
xian(item,type,blo){
let windowLeft = this.$refs[`canvas`].getBoundingClientRect().left
let windowtop = this.$refs[`canvas`].getBoundingClientRect().top
let div1Light = this.$refs[`${item.refs}`][0].getBoundingClientRect().left-windowLeft+220 //他变 往后走 + 30
let div1Top = this.$refs[`${item.refs}`][0].getBoundingClientRect().top-windowtop+25 //他不变
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.clearRect(0, 0, 522, 600);
ctx.beginPath();
//设置线条颜色为蓝色
let color = type=="good"?"#ef6363":"blue"
ctx.strokeStyle = color;
let guocuoXY = []
// if(this.linelianList.length==0)return
if(type=="good"){
console.log(this.linelianList)
let list = this.deepClone(this.abnormalStage)
this.abnormalStage = list.map(e=>{
let index = this.linelianList.findIndex(es=>es == e.stageId )
if(index==-1){
e.refs = ""
}
return e
})
console.log(list)
console.log(this.abnormalStage)
// this.abnormalStage = this.abnormalStage
}
if(type=="error"){
let list = this.deepClone(this.normalList)
this.normalList = list.map(e=>{
let index = this.linelianList.findIndex(es=>es == e.stageId )
if(index==-1){
e.refs = ""
}
return e
})
console.log(this.normalList)
// this.normalList = this.normalList
}
console.log(this.linelianList)
let list = type=="good"?this.abnormalStage:this.normalList
let size = type=="error"?0:230
console.log(size)
if(list.findIndex(e=>e.refs!='')>-1){
list.forEach(e=>{
if(e.refs != ''){
guocuoXY.push(
{
x:this.$refs[`${e.refs}`][0].getBoundingClientRect().left-windowLeft+220,
y:this.$refs[`${e.refs}`][0].getBoundingClientRect().top-windowtop+25,
}
)
}
})
console.log(guocuoXY)
guocuoXY.forEach(e=>{
//设置路径起点坐标
ctx.moveTo(div1Light,div1Top)
//定义中间点坐标1
ctx.lineTo((div1Light+e.x-220)/2,div1Top)
// //定义中间点坐标2
ctx.lineTo((div1Light+e.x-220)/2,e.y)
//定义中间点坐标3(这是最后一个中间点,也就是终点)
ctx.lineTo(e.x-size,e.y);
// let obj = guocuoXY[guocuoXY.length-1]
// console.log(obj)
var arrowX, arrowY;//箭头线终点坐标
var headlen = 10;//自定义箭头线的长度
var theta = 45;//自定义箭头线与直线的夹角,个人觉得45°刚刚好
var angle = Math.atan2(e.y - e.y, e.x+20 - e.x-size) * 180 / Math.PI;
var angle1 = (angle + theta) * Math.PI / 180;
var angle2 = (angle - theta) * Math.PI / 180;
var topX = headlen * Math.cos(angle1);
var topY = headlen * Math.sin(angle1);
var botX = headlen * Math.cos(angle2);
var botY = headlen * Math.sin(angle2);
arrowX = e.x-size + topX;
arrowY = e.y + topY;
//画上边箭头线
ctx.moveTo(arrowX, arrowY);
ctx.lineTo(e.x-size, e.y);
arrowX = e.x-size + botX;
arrowY = e.y + botY;
//画下边箭头线
ctx.lineTo(arrowX, arrowY);
})
ctx.lineWidth = 2;
// ctx.strokeStyle = "red";
ctx.stroke();
//关闭绘制路径
ctx.closePath();
console.log(blo)
}
// if(blo==undefined || blo==null){
// console.log("我进来啊啊啊啊啊"+blo)
// this.CaseInfo("1",item,type)
// }
console.log(this.normalListliu)
console.log(this.abnormalStageliu)
this.normalList = this.normalListliu
this.abnormalStage = this.abnormalStageliu
},
mounted(){
this.$nextTick(function() {
// 监听当前组件的滚动事件
this.$refs.listContent.addEventListener('scroll', ()=> {
this.xian(this.xianItem,this.xianItemType,"1")
},false)
});
}
@mouseenter // 你知道这个方法是干嘛用的嘛 留个彩蛋~~~~