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

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

スワイプ評価カードスタック

カードを左右にドラッグすると「NOPE」「LIKE」のラベルが浮かび上がり、離すと弾き飛んで次のカードが現れます。WordPressの求人マッチングやおすすめ提案UIに使えます。

dragjs

プレビュー

ソースコード

HTML

<div class="d08-08-06-stack">
          <div class="d08-08-06-card d08-08-06-pc d08-08-06-c3"><span class="d08-08-06-tag d08-08-06-like">LIKE</span><span class="d08-08-06-tag d08-08-06-nope">NOPE</span><b>Cさん</b></div>
          <div class="d08-08-06-card d08-08-06-pb d08-08-06-c2"><span class="d08-08-06-tag d08-08-06-like">LIKE</span><span class="d08-08-06-tag d08-08-06-nope">NOPE</span><b>Bさん</b></div>
          <div class="d08-08-06-card d08-08-06-pa d08-08-06-c1"><span class="d08-08-06-tag d08-08-06-like">LIKE</span><span class="d08-08-06-tag d08-08-06-nope">NOPE</span><b>Aさん</b></div>
        </div>

CSS

.d08-08-06-stack{position:relative;width:180px;height:200px}
        .d08-08-06-card{position:absolute;inset:0;border-radius:18px;display:flex;align-items:flex-end;justify-content:center;padding:16px;color:#fff;font-size:16px;font-weight:800;box-shadow:0 8px 20px rgba(30,30,60,.18);touch-action:pan-y;user-select:none;transition:transform .25s ease}
        .d08-08-06-pa{background:linear-gradient(135deg,#22c55e,#86efac)}
        .d08-08-06-pb{background:linear-gradient(135deg,#f59e0b,#fde68a)}
        .d08-08-06-pc{background:linear-gradient(135deg,#6a5cff,#a44bff)}
        .d08-08-06-c1{z-index:3;cursor:grab}
        .d08-08-06-c2{z-index:2;transform:scale(.95) translateY(8px)}
        .d08-08-06-c3{z-index:1;transform:scale(.9) translateY(16px)}
        .d08-08-06-tag{position:absolute;top:14px;font-size:11px;font-weight:800;border:2px solid #fff;border-radius:6px;padding:3px 8px;opacity:0}
        .d08-08-06-like{left:14px;color:#22c55e;border-color:#22c55e;background:rgba(255,255,255,.9);transform:rotate(-12deg)}
        .d08-08-06-nope{right:14px;color:#ef4444;border-color:#ef4444;background:rgba(255,255,255,.9);transform:rotate(12deg)}

JavaScript

(function(){
        var root=document.querySelector('#item-08-08-06 .d08-08-06');
        var stack=root&&root.querySelector('.d08-08-06-stack');
        if(!stack)return;
        var c1=stack.querySelector('.d08-08-06-c1'),c2=stack.querySelector('.d08-08-06-c2'),c3=stack.querySelector('.d08-08-06-c3');
        var order=[c1,c2,c3];
        var dragCard=null,startX=0;
        function getX(e){return e.touches&&e.touches.length?e.touches[0].clientX:e.clientX;}
        function setPos(el,pos){el.classList.remove('d08-08-06-c1','d08-08-06-c2','d08-08-06-c3');el.classList.add('d08-08-06-c'+pos);}
        function applyOrder(){setPos(order[0],1);setPos(order[1],2);setPos(order[2],3);}
        function resetTags(card){
          var like=card.querySelector('.d08-08-06-like'),nope=card.querySelector('.d08-08-06-nope');
          if(like)like.style.opacity=0;
          if(nope)nope.style.opacity=0;
        }
        function onDown(e){
          dragCard=this;
          dragCard.style.transition='none';
          startX=getX(e);
          document.addEventListener('mousemove',onMove);
          document.addEventListener('mouseup',onUp);
        }
        function onMove(e){
          if(!dragCard)return;
          if(e.cancelable)e.preventDefault();
          var x=getX(e)-startX;
          dragCard.style.transform='translateX('+x+'px) rotate('+(x/12)+'deg)';
          var like=dragCard.querySelector('.d08-08-06-like'),nope=dragCard.querySelector('.d08-08-06-nope');
          if(like)like.style.opacity=Math.max(0,Math.min(1,x/60));
          if(nope)nope.style.opacity=Math.max(0,Math.min(1,-x/60));
          dragCard.dataset.dx=x;
        }
        function onUp(){
          if(!dragCard)return;
          var card=dragCard;
          var x=parseFloat(card.dataset.dx||'0');
          document.removeEventListener('mousemove',onMove);
          document.removeEventListener('mouseup',onUp);
          dragCard=null;
          if(Math.abs(x)>70){
            card.style.transition='transform .4s ease';
            card.style.transform='translateX('+(x>0?420:-420)+'px) rotate('+(x>0?32:-32)+'deg)';
            card.style.opacity='0';
            setTimeout(function(){
              card.style.transition='none';
              card.style.transform='';
              card.style.opacity='';
              resetTags(card);
              order=[order[1],order[2],order[0]];
              applyOrder();
            },380);
          }else{
            card.style.transition='transform .25s ease';
            card.style.transform='';
            resetTags(card);
          }
          card.dataset.dx=0;
        }
        [c1,c2,c3].forEach(function(card){
          card.addEventListener('mousedown',onDown);
          card.addEventListener('touchstart',onDown,{passive:true});
          card.addEventListener('touchmove',onMove,{passive:false});
          card.addEventListener('touchend',onUp);
        });
      })();

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