React-hooks封裝無縫滑動輪播圖(js動畫,css動畫)

前言

因爲如今在基礎架構組,寫的項目也沒有ui框架,基本上都是要本身去封裝的。因而須要寫一個css

輪播圖組件,心想這不是分分鐘的事情嘛。說寫就寫...web

初版

思路:用ul li 的結構,再結合js定時器去實現輪播動畫,說幹就幹...markdown

無縫滑動原理: 紅色的1, 3都是克隆的過渡元素. index從 3 4 動畫結束時,立刻將指針滑動到1, 這樣就能夠實現無縫輪播. image.png架構

下面上js動畫僞代碼app

Carousel.tsx框架

interface Props {
    children: React.ReactNode
}
const PERCENTAGE = 100; // 百分比

const Carousel = (props: Props) => {

  const [left, setLeft] = useState(0)
  let  tempLeft = useRef(left);
  
  const transform = (target) => {
      let timer = setInterval(() => {
          if (Math.abs(tempLeft.current - target) <= 1 ) {
            clearInterval(timer)
            tempLeft.current = target;
            setLeft(target);
            
            if (target/PERCENTAGE >= len + 1) {
                // 此時已經滑動到咱們克隆的最後一張元素了
                setIndex(1). // 這裏就直接滑動到第一張完成無縫.
                setLeft(100)
                return
            }
            
          }
          
          
          let step = (target - tempLeft.current) / 10;
          step = step > 0 ? Math.ceil(step) : Math.floor(step);
          tempLeft.current = tempLeft.current + step;
          setLeft(() => tempLeft.current);
      }, 20)
  }

    return (
        <div className="carousel"> <ul className="carousel__container" style={{ left: `-${left}%`, width: (len + 2) * PERCENTAGE + "%" }} > {children[len - 1]} // 這裏將最後一個元素克隆到第一個 {children} {children[0]} // 這裏將第一個元素克隆到最後一個 </ul> </div>
    )

}


複製代碼

基本上無縫輪播就實現了,具體還須要加一個正在動畫的標識,防止用戶點的太快,發生異常。動畫

  • 這樣實現還會有幾個問題,頻繁改變state, 組件渲染次數過多. 所以咱們能夠考慮使用css實現動畫.
  • 使用定時器去完成動畫,可能還會發生不可描述的事...

第二版

css動畫ui

const transform = (target) => {

      timeoutId.current && clearTimeout(timeoutId.current);
      needAnimate.current = true;
      setLeft(target);

      if (target / 100 >= len + 1) {
        // 下面要不帶動畫的 滾動到真正的第一個元素
        timeoutId.current = setTimeout(() => {
          needAnimate.current = false;
          setLeft(100);
          setIndex(1);
        }, 350);
      }

    
}



    <ul
        style={{
            left: `-${index * 100}%`,
            width: (len + 2) * 100 + '%',
            transition: needAnimate.current ? "all 0.3s" : "none"
        }}
    
    >
        ...
    </ul>

複製代碼

上面就是這兩種寫法, 推薦仍是用css動畫比較好spa

相關文章
相關標籤/搜索