React实现无缝滚动并且封装一个滚动组件

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;
 }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值