在这里插入图片描述
首先 左边的线连接右边的线的话 都要准确找到双方的位置
所以我们通过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 // 你知道这个方法是干嘛用的嘛 留个彩蛋~~~~

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐