パーツ番号 08-15-05 ・ JavaScript使用
慣性で滑るドラッグリスト
チップを勢いよく振って離すと慣性で滑り、端では跳ね返って止まります。WordPressの日付選択バーやタグの横スクロールUIに応用できます。
プレビュー
ソースコード
HTML
<div class="d08-15-05-track" id="d08-15-05-track">
<div class="d08-15-05-row" id="d08-15-05-row">
<div class="d08-15-05-chip">Mon</div>
<div class="d08-15-05-chip">Tue</div>
<div class="d08-15-05-chip">Wed</div>
<div class="d08-15-05-chip">Thu</div>
<div class="d08-15-05-chip">Fri</div>
<div class="d08-15-05-chip">Sat</div>
<div class="d08-15-05-chip">Sun</div>
</div>
</div>CSS
.d08-15-05{width:100%;display:flex;align-items:center;justify-content:center}
.d08-15-05-track{position:relative;width:100%;max-width:250px;overflow:hidden;touch-action:none}
.d08-15-05-row{display:flex;gap:10px;width:max-content;cursor:grab}
.d08-15-05-row.is-drag{cursor:grabbing}
.d08-15-05-chip{flex:0 0 auto;background:#fff;border:1.5px solid #e2e2e8;border-radius:10px;padding:12px 16px;font-size:12.5px;font-weight:700;color:#2a2d3a;box-shadow:0 1px 3px rgba(0,0,0,.06);user-select:none}JavaScript
(function(){
var root=document.getElementById('item-08-15-05');if(!root)return;
var track=root.querySelector('#d08-15-05-track'),row=root.querySelector('#d08-15-05-row');
if(!track||!row)return;
var dragging=false,startX=0,startPos=0,pos=0,minPos=0,raf=null,hist=[];
function bounds(){minPos=Math.min(0,track.clientWidth-row.scrollWidth);}
function apply(p){row.style.transform='translateX('+p+'px)';}
row.addEventListener('pointerdown',function(e){
dragging=true;row.classList.add('is-drag');
if(raf)cancelAnimationFrame(raf);
bounds();startX=e.clientX;startPos=pos;hist=[{x:e.clientX,t:performance.now()}];
try{row.setPointerCapture(e.pointerId);}catch(err){}
});
row.addEventListener('pointermove',function(e){
if(!dragging)return;
var dx=e.clientX-startX;
var raw=startPos+dx;
if(raw>0)raw=raw*.35;
else if(raw<minPos)raw=minPos+(raw-minPos)*.35;
pos=raw;apply(pos);
hist.push({x:e.clientX,t:performance.now()});
if(hist.length>5)hist.shift();
});
function springTo(target){
var x=pos,v=0,stiff=.2,damp=.72;
function step(){
var f=(target-x)*stiff;v=(v+f)*damp;x+=v;pos=x;apply(x);
if(Math.abs(target-x)>.5||Math.abs(v)>.5){raf=requestAnimationFrame(step);}
else{pos=target;apply(target);}
}
raf=requestAnimationFrame(step);
}
function end(){
if(!dragging)return;
dragging=false;row.classList.remove('is-drag');
if(pos>0){springTo(0);return;}
if(pos<minPos){springTo(minPos);return;}
var a=hist[0],b=hist[hist.length-1];
var dt=(b&&a)?(b.t-a.t)||16:16;
var v=b&&a?(b.x-a.x)/dt*16:0;
var x=pos,raf2=null;
function momentum(){
x+=v;v*=.94;pos=x;
if(x>0){springTo(0);return;}
if(x<minPos){springTo(minPos);return;}
apply(x);
if(Math.abs(v)>.4){raf=requestAnimationFrame(momentum);}
}
if(Math.abs(v)>.4){raf=requestAnimationFrame(momentum);}
}
row.addEventListener('pointerup',end);
row.addEventListener('pointercancel',end);
})();クラス名 .d08-15-05 は本ライブラリ内での識別用です。複数のパーツを同じページで使う場合は、重複しないよう名前を変更してください。