因爲如今在基礎架構組,寫的項目也沒有ui框架,基本上都是要本身去封裝的。因而須要寫一個css
輪播圖組件,心想這不是分分鐘的事情嘛。說寫就寫...web
思路:用ul li 的結構,再結合js定時器去實現輪播動畫,說幹就幹...markdown
無縫滑動原理: 紅色的1, 3都是克隆的過渡元素. index從 3 4
動畫結束時,立刻將指針滑動到1, 這樣就能夠實現無縫輪播. 架構
下面上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>
)
}
複製代碼
基本上無縫輪播就實現了,具體還須要加一個正在動畫的標識,防止用戶點的太快,發生異常。動畫
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