@furious_whale/flyline
Version:
用 canvas 实现 HTML 元素之间相互连接飞线 支持vue2/vue3/原生
1 lines • 5.56 kB
JavaScript
import Flyline from"e-flyline";export default class FlyLine{constructor({responseData:t,arrowSize:e,lineMax:i,lineMin:s}){this.container=null,this.elementPosition=[],this.attrName="",this.lineData=[],this.responseData=t&&Array.isArray(t)?t:[],this.flylinePlugin=null,this.arrowSize=e||0===e?e:25,this.lineWMax=Number(i||5),this.lineWMin=Number(s||1),this.lineWD=Math.abs(this.lineWMax-this.lineWMin)}init(s,o){s&&o&&(this.container=s,this.attrName=o,this.container.querySelectorAll(`[${o}]`).forEach(t=>{var e,i=t.getAttribute(o);i&&(e=this.getElToBoxPosition(t),this.elementPosition.push({labelid:i,left:e.left,top:e.top,bottom:e.top+t.offsetHeight,right:e.left+t.offsetWidth,centerTop:e.top+t.offsetHeight/2,centerLeft:e.left+t.offsetWidth/2,height:t.offsetHeight,width:t.offsetWidth,prentWidth:s.offsetWidth,prentHeight:s.offsetHeight}))}),this.flylinePlugin=new Flyline(this.container,{arrow:{size:this.arrowSize},loop:t=>{this.loop&&this.loop(t)},click:t=>{this.click&&this.click(t)},move:t=>{this.move&&this.move(t)}},this.responseData))}destroy(){this.flylinePlugin&&this.flylinePlugin.destroy()}draw(n){this.lineData=[];let e=0,a=Number.MAX_SAFE_INTEGER;if(n&&n.length){n.forEach(t=>{t=t.width||0;t>e&&(e=t),t<a&&(a=t)});let r=e-a;n.forEach(o=>{var t=this.elementPosition.find(t=>t.labelid===o.from),h=this.elementPosition.find(t=>t.labelid===o.to);if(t&&h){let e=[],i=[];switch(o.start){case"left":e.push(t.left),e.push(t.centerTop);break;case"right":e.push(t.right),e.push(t.centerTop);break;case"top":e.push(t.centerLeft),e.push(t.top);break;case"bottom":e.push(t.centerLeft),e.push(t.bottom);break;case"center":e.push(t.centerLeft),e.push(t.centerTop);break;case"leftTop":e.push(t.left),e.push(t.centerTop-t.height/2);break;case"leftBottom":e.push(t.left),e.push(t.centerTop+t.height/2);break;case"topLeft":e.push(t.centerLeft-t.width/2),e.push(t.top);break;case"topRight":e.push(t.centerLeft+t.width/2),e.push(t.top);break;case"rightTop":e.push(t.right),e.push(t.centerTop-t.height/2);break;case"rightBottom":e.push(t.right),e.push(t.centerTop+t.height/2);break;case"bottomLeft":e.push(t.centerLeft-t.width/2),e.push(t.bottom);break;case"bottomRight":e.push(t.centerLeft+t.width/2),e.push(t.bottom);break;default:e.push(t.right),e.push(t.centerTop)}switch(o.end){case"left":i.push(h.left),i.push(h.centerTop);break;case"right":i.push(h.right),i.push(h.centerTop);break;case"top":i.push(h.centerLeft),i.push(h.top);break;case"bottom":i.push(h.centerLeft),i.push(h.bottom);break;case"center":i.push(h.centerLeft),i.push(h.centerTop);break;case"leftTop":i.push(h.left),i.push(h.centerTop-t.height/2);break;case"leftBottom":i.push(h.left),i.push(h.centerTop+t.height/2);break;case"topLeft":i.push(h.centerLeft-t.width/2),i.push(h.top);break;case"topRight":i.push(h.centerLeft+t.width/2),i.push(h.top);break;case"rightTop":i.push(h.right),i.push(h.centerTop-t.height/2);break;case"rightBottom":i.push(h.right),i.push(h.centerTop+t.height/2);break;case"bottomLeft":i.push(h.centerLeft-t.width/2),i.push(h.bottom);break;case"bottomRight":i.push(h.centerLeft+t.width/2),i.push(h.bottom);break;default:i.push(h.left),i.push(h.centerTop)}let s=[e];o.type&&"angle"==o.type&&o.path&&o.path.length&&(s=s.concat(o.path.filter(t=>t[0]&&t[1]).map(t=>this.processPoint(t,s,{startPosition:e,endPosition:i})))),(s=o.type&&"curve"==o.type?s.concat([this.delCurvePath(o,e,i)]):s).push(i),this.lineData.push({startPosition:e,endPosition:i,points:s,id:o.id||o.from+"_"+o.to,...o,width:1==n.length?this.lineWMin+this.lineWD/2:this.lineWMin+((o.width||0)-a)/r*this.lineWD,curve:"curve"==o.type})}})}this.flylinePlugin.draw(this.lineData)}delCurvePath(e,i,t){let s=i[0],o=i[1];var h=t[0]-i[0],t=t[1]-i[1];let r=Math.abs(h/3),n=Math.abs(t/3);t<h?r=Math.max(r,60):h<t&&(n=Math.max(n,60));i={left:()=>s-=r,right:()=>s+=r,top:()=>o-=n,bottom:()=>o+=n};if(e.start){let t="right";e.start.startsWith("left")&&(t="left"),e.start.startsWith("top")&&(t="top"),i[t=e.start.startsWith("bottom")?"bottom":t]&&i[t]()}return[s,o]}processPoint(t,e,i){var s=this.pointPx(t,i);return String(t[0]).startsWith("i")&&(s[0]=e[e.length-1][0]+this.delInheritX(t[0],i)),String(t[1]).startsWith("i")&&(s[1]=e[e.length-1][1]+this.delInheritY(t[1],i)),String(t[0]).startsWith("e")&&(s[0]=i.endPosition[0]+this.delInheritX(t[0],i)),String(t[1]).startsWith("e")&&(s[1]=i.endPosition[1]+this.delInheritY(t[1],i)),s}delInheritX(t,e){var i;return t?t.includes("-")?([,i]=t.split("-"),-this.pointPx([i,0],e)[0]):t.includes("+")?([,i]=t.split("+"),this.pointPx([i,0],e)[0]):0:0}delInheritY(t,e){var i;return t?t.includes("-")?([,i]=t.split("-"),-this.pointPx([0,i],e)[1]):t.includes("+")?([,i]=t.split("+"),this.pointPx([0,i],e)[1]):0:0}convertToPx(t,e){var i=String(t).includes("%"),t=parseFloat(t);return i?Number((t/100*e).toFixed(2)):t}pointPx([t,e],i){var s=i.endPosition[0]-i.startPosition[0],i=i.endPosition[1]-i.startPosition[1];return[Number(this.convertToPx(t,s)),Number(this.convertToPx(e,i))]}getElToBoxPosition(t){let e=t.offsetTop,i=t.offsetLeft,s=0,o=0;var h=window.getComputedStyle(t),h=(h.transform&&"none"!==h.transform&&((h=h.transform.split("(")[1].split(")")[0].split(","))[4]&&(s=Number(h[4].trim())),h[5])&&(o=Number(h[5].trim())),i+=s,e+=o,this.getPositionParent(t));return h&&h!==this.container&&(t=this.getElToBoxPosition(h),i+=t.left,e+=t.top),{left:i,top:e}}getPositionParent(t){var e;return t.parentNode?!(e=window.getComputedStyle(t.parentNode)).position||"absolute"!==e.position&&"relative"!==e.position?t.parentNode?this.getPositionParent(t.parentNode):null:t.parentNode:null}}