鏈接兩個div的直線,拖動時保持連線。

效果:鏈接兩個div帶箭頭的虛線,拖動div時保持線條實時改變位置保持始終鏈接

效果圖:
圖片描述javascript

1.產品經理提出的需求

用帶箭頭的虛線將兩個位置不固定的div鏈接起來,初聽到這個需求一頭霧水,傳統的div能夠作直線,但斜起來不太好作,幸好以前接觸過svg,裏面有一個line標籤,知道起始停止兩個點的位置,就能夠將兩個點鏈接起來了。
至於箭頭,能夠這麼作先定義箭頭:css

<svg>
          <defs>
              <marker id="arrow" markerUnits="strokeWidth" markerWidth="12" markerHeight="12" viewBox="0 0 12 12" refX="6" refY="6" orient="auto">
                  <path xmlns="http://www.w3.org/2000/svg" d="M2,2 L10,6 L2,10 L6,6 L2,2" style="fill: #000000;" />
              </marker>
          </defs>
      </svg>

將箭頭放在直線上:marker-end="url(#arrow)"java

<line  x1="0" y1="0" x2="200" y2="50" stroke="#000" stroke-width="2" marker-end="url(#arrow)"stroke-dasharray="10,10"></line>

2.肯定起始停止兩個點左上角的位置

須要鏈接的兩個div及SVG都相對於某一個div.wrap絕對定位,能夠先求得兩個div左上角相對與div.wrap座標:git

//獲取元素左上角相對於某一元素的的位置
      function getElCoordinate(dom) {
                  var t = dom.offsetTop;
                  var l = dom.offsetLeft;
                  var w = dom.offsetWidth;
                  var h = dom.offsetHeight;
                  dom = dom.offsetParent;
                  while (!$(dom).hasClass('wrap')) {
                      t += dom.offsetTop;
                      l += dom.offsetLeft;
                      dom = dom.offsetParent;
                  }; return {
                      top: t,//Y軸座標
                      left: l,//X軸座標
                      width:w,//元素寬度
                      height:h//元素高度 
                  };
              }
     })

3.肯定鏈接點在div上的位置:

分爲兩種狀況:終點div位於起點div上方,終點div位於起點div下方。github

var pos1 = getElCoordinate($('.item1')[0])//起點div的位置
   var pos2 = getElCoordinate($('.item2')[0])//終點div的位置
   function getPos(pos1, pos2){
              //分兩種狀況
              var x1,y1,x2,y2;
              if(pos2.top<pos1.top){
                  x1 = pos1.left + pos1.width/2;
                  y1 = pos1.top;
                  y2 = pos2.top + pos2.height
                 if(pos2.left<pos1.left){
                    x2 = pos2.left + pos2.width/2
              }else{
                  x1 = pos1.left + pos1.width / 2;
                  y1 = pos1.top + pos1.height;
                  x2 = pos2.left + pos2.width/2
                  y2 = pos2.top 
              }
              return {
                  start :{x:x1,y:y1},
                  end : {x:x2,y:y2}
              }
           }

4.肯定起止點位置後連線。

function move(){
               var pos1 = getElCoordinate($('.item1')[0])
               var pos2 = getElCoordinate($('.item2')[0])
               var start = getPos(pos1, pos2).start
               var end = getPos(pos1, pos2).end

               $('#line').attr({ x1: start.x, y1: start.y, x2: end.x, y2: end.y })
               $('#path').attr({ d: 'M20,20 L100,100' })
           }
           move()

5.兩個div分別拖動並保持線始終鏈接

drag($('.item'), move)
             function drag(obj,callback) {
                var dragEles = obj;
                dragEles.each(function(index, dragEleDom){
                    var _move = false;//移動標記
                    var _x, _y;//鼠標離控件左上角的相對位置
                    var dragEle = $(dragEleDom)
                    dragEle.click(function () {
                        //alert("click");//點擊(鬆開後觸發)
                    }).mousedown(function (e) {
                        _move = true;
                        _x = e.pageX - parseInt(dragEle.css("left"));
                        _y = e.pageY - parseInt(dragEle.css("top"));
                        // dragEle.fadeTo(20, 0.9);//點擊後開始拖動並透明顯示
                    });
                    $(document).mousemove(function (e) {
                        if (_move) {
                            var x = e.pageX - _x;//移動時根據鼠標位置計算控件左上角的絕對位置
                            var y = e.pageY - _y;
                            dragEle.css({ top: y, left: x });//控件新位置
                            if(callback){callback()}
                        }
                    }).mouseup(function () {
                        _move = false;
                        dragEle.fadeTo("fast", 1);//鬆開鼠標後中止移動並恢復成不透明
                    });
                })
                
           }

梳理下流程:分析需求>肯定使用SVG>找到鏈接點>連線>拖動時保持連線。

源碼託管於github歡迎star

相關文章
相關標籤/搜索