← 動的パーツギャラリーへ戻る

パーツ番号 08-15-06 ・ JavaScript使用

ゴムひも風ドラッグ接続線

丸ノードをドラッグすると接続線が伸びて細くなり、離すとバネのように起点へ跳ね戻ります。WordPressの相関図やマインドマップ風演出に使えます。

dragjs

プレビュー

ソースコード

HTML

<div class="d08-15-06-stage" id="d08-15-06-stage">
          <svg class="d08-15-06-svg" viewBox="0 0 240 170" preserveAspectRatio="none">
            <line class="d08-15-06-line" id="d08-15-06-line" x1="36" y1="30" x2="36" y2="30"></line>
            <circle class="d08-15-06-anchor" cx="36" cy="30" r="7"></circle>
          </svg>
          <div class="d08-15-06-node" id="d08-15-06-node" style="left:36px;top:30px"></div>
        </div>

CSS

.d08-15-06{width:100%;display:flex;align-items:center;justify-content:center}
        .d08-15-06-stage{position:relative;width:100%;max-width:240px;height:170px}
        .d08-15-06-svg{position:absolute;inset:0;width:100%;height:100%}
        .d08-15-06-line{stroke:#8b5cf6;stroke-width:4;stroke-linecap:round}
        .d08-15-06-anchor{fill:#2a2d3a}
        .d08-15-06-node{position:absolute;width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#6a5cff,#8b5cf6);transform:translate(-50%,-50%);cursor:grab;touch-action:none;box-shadow:0 4px 10px rgba(106,92,255,.35)}
        .d08-15-06-node.is-drag{cursor:grabbing}

JavaScript

(function(){
        var root=document.getElementById('item-08-15-06');if(!root)return;
        var stage=root.querySelector('#d08-15-06-stage'),node=root.querySelector('#d08-15-06-node'),line=root.querySelector('#d08-15-06-line');
        if(!stage||!node||!line)return;
        var AX=36,AY=30,dragging=false,ox=0,oy=0,px=AX,py=AY,raf=null,vbW=240,vbH=170;
        function place(x,y){
          node.style.left=x+'px';node.style.top=y+'px';
          line.setAttribute('x2',x);line.setAttribute('y2',y);
          var dist=Math.sqrt((x-AX)*(x-AX)+(y-AY)*(y-AY));
          line.setAttribute('stroke-width',Math.max(1.5,4-dist/60));
        }
        node.addEventListener('pointerdown',function(e){
          dragging=true;node.classList.add('is-drag');
          if(raf)cancelAnimationFrame(raf);
          var r=stage.getBoundingClientRect();
          ox=r.left;oy=r.top;
          try{node.setPointerCapture(e.pointerId);}catch(err){}
        });
        node.addEventListener('pointermove',function(e){
          if(!dragging)return;
          var r=stage.getBoundingClientRect();
          var x=(e.clientX-r.left)/r.width*vbW;
          var y=(e.clientY-r.top)/r.height*vbH;
          x=Math.max(0,Math.min(vbW,x));y=Math.max(0,Math.min(vbH,y));
          px=x;py=y;place(x,y);
        });
        function end(){
          if(!dragging)return;
          dragging=false;node.classList.remove('is-drag');
          var x=px,y=py,vx=0,vy=0,stiff=.17,damp=.74;
          function step(){
            var fx=(AX-x)*stiff,fy=(AY-y)*stiff;
            vx=(vx+fx)*damp;vy=(vy+fy)*damp;
            x+=vx;y+=vy;place(x,y);
            if(Math.abs(AX-x)>.5||Math.abs(AY-y)>.5||Math.abs(vx)>.5||Math.abs(vy)>.5){
              raf=requestAnimationFrame(step);
            }else{place(AX,AY);}
          }
          raf=requestAnimationFrame(step);
        }
        node.addEventListener('pointerup',end);
        node.addEventListener('pointercancel',end);
      })();

クラス名 .d08-15-06 は本ライブラリ内での識別用です。複数のパーツを同じページで使う場合は、重複しないよう名前を変更してください。