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

パーツ番号 08-08-03 ・ JavaScript使用

スワイプで開くボトムシート

下部のシートを上へドラッグすると詳細パネルがせり上がって開きます。WordPressの商品詳細やフィルター設定パネルに使えるモバイル向けUIです。

mobilescrolldragjsoverlay

プレビュー

ソースコード

HTML

<div class="d08-08-03-wrap">
          <div class="d08-08-03-bg">上にスワイプでシートを開く</div>
          <div class="d08-08-03-sheet">
            <div class="d08-08-03-handle"></div>
            <p class="d08-08-03-title">詳細オプション</p>
            <p class="d08-08-03-desc">配送方法や支払い方法をここから選択できます。</p>
          </div>
        </div>

CSS

.d08-08-03-wrap{position:relative;width:100%;max-width:280px;height:210px;border-radius:16px;overflow:hidden;background:linear-gradient(160deg,#eef1ff,#dfe4ff)}
        .d08-08-03-bg{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#7b81a3;font-size:12px;font-weight:600;text-align:center;padding:0 30px;cursor:pointer}
        .d08-08-03-sheet{position:absolute;left:0;right:0;bottom:0;background:#fff;border-radius:18px 18px 0 0;box-shadow:0 -6px 20px rgba(30,30,60,.12);padding:10px 18px 18px;transform:translateY(78%);touch-action:none;cursor:grab}
        .d08-08-03-handle{width:36px;height:4px;border-radius:2px;background:#d8dae2;margin:2px auto 12px}
        .d08-08-03-title{font-size:13.5px;font-weight:700}
        .d08-08-03-desc{font-size:11.5px;color:#8a8f9c;margin-top:6px}

JavaScript

(function(){
        var root=document.querySelector('#item-08-08-03 .d08-08-03');
        var sheet=root&&root.querySelector('.d08-08-03-sheet');
        var bg=root&&root.querySelector('.d08-08-03-bg');
        if(!sheet)return;
        var open=false,dragging=false,startY=0,baseY=0,lastY=0;
        function getY(e){return e.touches&&e.touches.length?e.touches[0].clientY:e.clientY;}
        function closedY(){return Math.max(0,sheet.offsetHeight-34);}
        function apply(y){
          y=Math.max(0,Math.min(closedY(),y));
          lastY=y;
          sheet.style.transform='translateY('+y+'px)';
        }
        function onDown(e){
          dragging=true;
          sheet.style.transition='none';
          startY=getY(e);
          baseY=open?0:closedY();
          document.addEventListener('mousemove',onMove);
          document.addEventListener('mouseup',onUp);
        }
        function onMove(e){
          if(!dragging)return;
          if(e.cancelable)e.preventDefault();
          apply(baseY+(getY(e)-startY));
        }
        function onUp(){
          if(!dragging)return;
          dragging=false;
          document.removeEventListener('mousemove',onMove);
          document.removeEventListener('mouseup',onUp);
          sheet.style.transition='transform .3s cubic-bezier(.2,.8,.2,1)';
          open=lastY<closedY()/2;
          sheet.classList.toggle('is-open',open);
          apply(open?0:closedY());
        }
        sheet.addEventListener('mousedown',onDown);
        sheet.addEventListener('touchstart',onDown,{passive:true});
        sheet.addEventListener('touchmove',onMove,{passive:false});
        sheet.addEventListener('touchend',onUp);
        if(bg)bg.addEventListener('click',function(){
          if(!open){open=true;sheet.style.transition='transform .3s cubic-bezier(.2,.8,.2,1)';sheet.classList.add('is-open');apply(0);}
          else{open=false;sheet.style.transition='transform .3s cubic-bezier(.2,.8,.2,1)';sheet.classList.remove('is-open');apply(closedY());}
        });
        apply(closedY());
      })();

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