パーツ番号 08-15-01 ・ JavaScript使用
バネで戻るエラスティックノブ
ノブを外周までドラッグして離すと、バネのように弾んで中心に戻ります。WordPressのジョイスティック風操作や感情スタンプの強度入力UIに応用できます。
プレビュー
ソースコード
HTML
<div class="d08-15-01-field" id="d08-15-01-field">
<div class="d08-15-01-ring"></div>
<div class="d08-15-01-knob" id="d08-15-01-knob"></div>
</div>CSS
.d08-15-01{width:100%;display:flex;align-items:center;justify-content:center}
.d08-15-01-field{position:relative;width:150px;height:150px}
.d08-15-01-ring{position:absolute;inset:0;border:2px dashed #d8d5ff;border-radius:50%}
.d08-15-01-ring::after{content:"";position:absolute;top:50%;left:50%;width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;background:#d8d5ff}
.d08-15-01-knob{position:absolute;top:50%;left:50%;width:46px;height:46px;margin:-23px 0 0 -23px;border-radius:50%;background:linear-gradient(135deg,#6a5cff,#8b5cf6);box-shadow:0 6px 16px rgba(106,92,255,.35);cursor:grab;touch-action:none}
.d08-15-01-knob.is-drag{cursor:grabbing}JavaScript
(function(){
var root=document.getElementById('item-08-15-01');if(!root)return;
var field=root.querySelector('#d08-15-01-field'),knob=root.querySelector('#d08-15-01-knob');
if(!field||!knob)return;
var dragging=false,cx=0,cy=0,px=0,py=0,raf=null,MAXR=52;
function apply(x,y){knob.style.transform='translate('+x+'px,'+y+'px)';}
knob.addEventListener('pointerdown',function(e){
dragging=true;knob.classList.add('is-drag');
if(raf)cancelAnimationFrame(raf);
var r=field.getBoundingClientRect();cx=r.left+r.width/2;cy=r.top+r.height/2;
try{knob.setPointerCapture(e.pointerId);}catch(err){}
});
knob.addEventListener('pointermove',function(e){
if(!dragging)return;
var dx=e.clientX-cx,dy=e.clientY-cy;
var dist=Math.sqrt(dx*dx+dy*dy);
if(dist>MAXR){
var extra=dist-MAXR;
var damped=MAXR+Math.sqrt(extra)*4;
var scale=damped/dist;
dx*=scale;dy*=scale;
}
px=dx;py=dy;apply(dx,dy);
});
function end(){
if(!dragging)return;
dragging=false;knob.classList.remove('is-drag');
var x=px,y=py,vx=0,vy=0,stiff=.18,damp=.72;
function step(){
var fx=(0-x)*stiff,fy=(0-y)*stiff;
vx=(vx+fx)*damp;vy=(vy+fy)*damp;
x+=vx;y+=vy;apply(x,y);
if(Math.abs(x)>.5||Math.abs(y)>.5||Math.abs(vx)>.5||Math.abs(vy)>.5){
raf=requestAnimationFrame(step);
}else{apply(0,0);}
}
raf=requestAnimationFrame(step);
}
knob.addEventListener('pointerup',end);
knob.addEventListener('pointercancel',end);
})();クラス名 .d08-15-01 は本ライブラリ内での識別用です。複数のパーツを同じページで使う場合は、重複しないよう名前を変更してください。