パーツ番号 08-15-06 ・ JavaScript使用
ゴムひも風ドラッグ接続線
丸ノードをドラッグすると接続線が伸びて細くなり、離すとバネのように起点へ跳ね戻ります。WordPressの相関図やマインドマップ風演出に使えます。
プレビュー
ソースコード
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 は本ライブラリ内での識別用です。複数のパーツを同じページで使う場合は、重複しないよう名前を変更してください。