React实现无缝滚动并且封装一个滚动组件
前言
实现无缝滚动的思路有很多种,这里使用的主要思路如下。
假设有一个需要滚动的块A,我们复制一个A为B,A和B一模一样,之后我们去滚动AB这个整体,从A开始滚动,当滚动到B边界的时候,就把整体的滚动回到初始状态,又重新开始在A滚动,这里因为B和A是一摸一样的 所以肉眼根本看不出这是A还是B 或者卡顿
一、代码实现
附上代码 注意把滚动条隐藏,这里使用的是hooks 这里useEffect的作用和componentDidMount类似
import React, {useEffect} from 'react';
const style = {
ul: {
margin: 0,
padding: 0,
width:"600px",
height: "50px",
},
li: {
listStyle: "none",
width: "200px",
height: "50px",
float: "left"
},
content:{
overflow: "auto",
maxWidth: "600px",
display: "flex"
},
}
function MainBody(props) {
useEffect(() => {
let timer
let dome = document.getElementById("scroll")
let dome1 = document.getElementById("scroll-1")
let dome2 = document.getElementById("scroll-2")
dome2.innerHTML = dome1.innerHTML//复制dome1 为dome2
let AniTimerScroll = () => {
timer = setTimeout(function () {
if (dome.scrollLeft == dome1.clientWidth) {
dome.scrollLeft = 0;
} else {
dome.scrollLeft++;
}
AniTimerScroll()
}, 20);
}
AniTimerScroll();
}, [])
return (
<div className='app-content' style={style.content} id="scroll">
<div id="scroll-1">
<ul style={style.ul}>
<li style={{ backgroundColor: "red", ...style.li }}></li>
<li style={{ backgroundColor: "green", ...style.li }}></li>
<li style={{ backgroundColor: "blue", ...style.li }}></li>
</ul>
</div>
<div id="scroll-2"></div>
</div>
)
}
二、封装组件
接下来为了方便使用,需要把它封装成一个组件 将包裹的组件进行无缝滚动,根据思路 如下设计组件
首先利用React.Children和 React.cloneElement复制一个包裹的组件,再用上述方法进行滚动代码如下
import React, { useEffect, Children, useRef } from 'react';
const style = {
ul: {
margin: 0,
padding: 0,
width: "600px",
height: "50px",
},
li: {
listStyle: "none",
width: "200px",
height: "50px",
float: "left"
},
content: {
overflow: "auto",
maxWidth: "600px",
display: "flex",
alignItems: "flex-start"
},
}
function MainBody(props) {
return (
<div className='app-content' style={style.content} id="scroll">
<Scroll>
<div>
<ul style={style.ul}>
<li style={{ backgroundColor: "red", ...style.li }}></li>
<li style={{ backgroundColor: "green", ...style.li }}></li>
<li style={{ backgroundColor: "blue", ...style.li }}></li>
</ul>
</div>
</Scroll>
</div>
)
}
function Scroll(props) {
const scroll = useRef(null)
const scrollSource = useRef(null)
const scrollClone = useRef(null)
useEffect(() => {
let timer
let AniTimerScroll = () => {
timer = setTimeout(function () {
if (scroll.current.scrollLeft == scrollSource.current.clientWidth) {
scroll.current.scrollLeft = 0;
} else {
scroll.current.scrollLeft++;
}
AniTimerScroll()
}, 20);
}
AniTimerScroll();
}, [])
return <div style={style.content} ref={scroll}>
{
Children.map(props.children, child => {
return [//复制一份包裹的组件
React.cloneElement(child, {
ref: scrollSource
}),
React.cloneElement(child, {
ref: scrollClone
})
]
})
}
</div>
}
React.Children:用于处理子节点
React.cloneElement:克隆并且传递新的props
useRef:创建ref对象
接下来用css隐藏掉滚动条就ok了
如:
.app-content::-webkit-scrollbar {
height: 5px;
display: none;
}