FLIP动画

123 阅读1分钟

GIF 2023-10-17 10-22-44.gif

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>FLIP 动画</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }
    ul,li {
      list-style: none;
    }
    ul {
      border: 1px solid gold;
      padding: 20px;
      width: 300px;
    }
    li {
      height: 40px;
      background: goldenrod;
      border-radius: 20px;
      margin-bottom: 5px;
      text-align: center;
      line-height: 40px;
    }
    li:last-child {
      background: red;
    }
  </style>
</head>
<body>
  <button id="btn">run</button>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
  </ul>
  <script>
    const list = document.querySelector('ul')
    const btn = document.getElementById('btn')

    btn.onclick = () => {
      const firstItem = document.querySelector('li')

      const dis = getDistance(firstItem)
      addTransition(firstItem, dis)

      raf(() => {
        firstItem.style.transition = 'transform 5s'
        firstItem.style.removeProperty('transform')
      })
    }
    
    function getDistance(firstItem) {
      const start = getLocation(firstItem)
  
      list.insertBefore(firstItem, null)
      
      const end = getLocation(firstItem)
      const dis = start - end
      return dis
    }
    
    function addTransition(firstItem, dis) {
      firstItem.style.removeProperty('transition')
      firstItem.style.transform = `translateY(${dis}px)`
    }

    function raf(cb) {
      requestAnimationFrame(() => {
        requestAnimationFrame(cb)
      })
    }

    function getLocation(firstItem) {
      const react = firstItem.getBoundingClientRect()
      return react.top
    }
    </script>
</body>
</html>