因为如今在基础架构组,写的项目也没有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