效果如图:
创建1个message-list
文件夹,里面存放两个文件,index.tsx
和style.less
:
原理是就设置一个固定长度的父节点,然后消息内容的长度超过了父节点的长度,就会出现滚动条,这个时候设置一个定时器,让子节点即消息内容,一步步的向左边滚动,当向左边滚动完成以后马上需要回到原始位置,再重新滚动。
1.index.tsx
import { useEffect, useRef, useState } from 'react'
import './style.less'
function App(props) {
const [isScrolle, setIsScrolle] = useState(true) //控制是否滚动
const [context, setContext] = useState([]) //滚动消息
const speed = 25 //滚动速度,值越小,滚动越快
const warper: any = useRef() //对应parent的节点
const childDomInit: any = useRef() //初始的消息节点
const childDomCopy: any = useRef() //复制的消息节点
useEffect(() => {
setContext(props.messageData)
childDomCopy.current.innerHTML = childDomInit.current.innerHTML // 复制了一层节点,拼在原有节点后面,使得它看起来像无线滚动一样
}, [props])
// 开始滚动
useEffect(() => {
let timer
if (isScrolle) {
timer = setInterval(() => {
/**
*让消息持续的向左滚动
* warper.current.scrollLeft:内容向左边滚动的距离
* childDomInit.current.scrollWidth :内容的长度
*/
warper.current.scrollLeft >= childDomInit.current.scrollWidth
? (warper.current.scrollLeft = 0)
: warper.current.scrollLeft++
}, speed)
}
return () => {
clearTimeout(timer)
}
}, [isScrolle])
// 鼠标移动,移除方法
const hoverHandler = (flag) => setIsScrolle(flag)
return (
<>
<div>
<span className="mesage-text">消息通知:</span>
<div className="parent" ref={warper} style={{ marginLeft: '90px' }}>
<div className="child" ref={childDomInit}>
{context.map((item: any, index) => (
<span
key={index}
onMouseOver={() => hoverHandler(false)}
onMouseLeave={() => hoverHandler(true)}
>
<span style={{ fontSize: '16px' }}>{index + 1}.</span>
{item.datetime}
</span>
))}
</div>
<div className="child" ref={childDomCopy}></div>
</div>
</div>
</>
)
}
export default App
2.style.less
.parent {
display: flex;
height: 50px;
overflow-x: scroll;
scrollbar-width: none;
-ms-overflow-style: none;
}
.parent::-webkit-scrollbar {
display: none;
}
/*设置的子盒子高度大于父盒子,产生溢出效果*/
.child {
display: inline-block;
height: 50px;
line-height: 50px;
white-space: nowrap;
}
.child > span {
height: 50px;
margin: 2px 0;
white-space: nowrap;
}
.mesage-text {
position: absolute;
margin-left: 10px;
height: 50px;
line-height: 50px;
}