Javascript React中的简单旋转木马-如何注册滚动到下一张幻灯片?
这是一个相对简单的问题,但我一直未能解决它。我构建了以下转盘/滑块:Javascript React中的简单旋转木马-如何注册滚动到下一张幻灯片?,javascript,css,reactjs,carousel,react-hooks,Javascript,Css,Reactjs,Carousel,React Hooks,这是一个相对简单的问题,但我一直未能解决它。我构建了以下转盘/滑块: const BlogPostCardSlider = ({ children }) => { const [activeSlide, setActiveSlide] = useState(0); const activeSlideRef = useRef(null); const wrapperRef = useRef(null); const firstRenderRef = useRef(true);
const BlogPostCardSlider = ({ children }) => {
const [activeSlide, setActiveSlide] = useState(0);
const activeSlideRef = useRef(null);
const wrapperRef = useRef(null);
const firstRenderRef = useRef(true);
useEffect(() => {
if (firstRenderRef.current) {
//this is checking whether its the first render of the component. If it is, we dont want useEffect to run.
firstRenderRef.current = false;
} else if (activeSlideRef.current) {
activeSlideRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'nearest'
});
}
}, [activeSlide]);
const moveRight = () => {
if (activeSlide + 1 >= children.length) {
return children.length - 1;
}
return activeSlide + 1;
};
const moveLeft = () => {
if (activeSlide - 1 <= 0) {
return 0;
}
return activeSlide - 1;
};
return (
<div id="trap" tabIndex="0">
<button onClick={() => setActiveSlide(moveLeft)}>PREV</button>
{children.map((child, i) => {
return (
<SlideLink
key={`slideLink-${i}`}
isActive={activeSlide === i}
onClick={e => {
setActiveSlide(i);
}}
>
{i + 1}
</SlideLink>
);
})}
<Wrapper
onScroll={e => {
let { width } = wrapperRef.current.getBoundingClientRect();
let { scrollLeft } = wrapperRef.current;
if ((scrollLeft / width) % 1 === 0) {
setActiveSlide(scrollLeft / width);
}
}}
ref={wrapperRef}
>
{children.map((child, i) => {
return (
<Slide
key={`slide-${i}`}
ref={i === activeSlide ? activeSlideRef : null}
>
{child}
</Slide>
);
})}
</Wrapper>
<button onClick={() => setActiveSlide(moveRight)}>NEXT</button>
</div>
);
};
export default BlogPostCardSlider;
…这样做的结果是,setActiveSlide
仅在幻灯片完全显示在视图中时调用。这会产生一种滞后的体验:用户已滚动到下一张幻灯片,下一张幻灯片显示在视图中,但计算尚未完成(因为只有在幻灯片100%显示在视图中时才完成),因此,在这个过程中,活动的SlideLink会在很晚的时候更新
我该如何解决这个问题?有什么方法可以乐观地更新这个吗?乍一看,我认为这应该是一个快速解决方案。结果证明需要更多一点。我在这里创建了一个工作示例:
要点是,在
onScroll
事件期间不应调用setActiveSide
,而应在用户完成滚动时调用。这是在示例中使用onIdlereact钩子实现的。您可以稍微修改计算,以便当幻灯片在视图中超过50%时,将active属性设置为该属性
onScroll={e => {
let { width } = wrapperRef.current.getBoundingClientRect();
let { scrollLeft } = wrapperRef.current;
setActiveSlide(Math.round(scrollLeft / width) + 1);
}}
示例:宽度为800px的旋转木马,总幻灯片数为3张。所以,scrollLeft将从0到1600变化
- 从0到400:活动幻灯片=数学圆(滚动左/宽)=第0个索引 (或第一张幻灯片)
- 从400-1200:活动幻灯片=第一个索引(或第二个索引 幻灯片)因为它更多地出现在视图中
- 从1200-1600:活动幻灯片= 第二个索引(或第三张幻灯片),因为它更在视图中
希望能有帮助。如果有任何疑问,请回复。如果您在此处提供演示,我认为这将非常有用。
onScroll={e => {
let { width } = wrapperRef.current.getBoundingClientRect();
let { scrollLeft } = wrapperRef.current;
setActiveSlide(Math.round(scrollLeft / width) + 1);
}}