使用react浅显的了解一下无缝轮播图是如何实现的

  1. 首先接收一个url, 类型为Array的数组, 使用map对数组进行循环渲染,数组渲染前放入"<img"标签,渲染数组的最后一项
  2. 在数组渲染后放"<img"标签, 渲染数组的第一项;
  3. 没什么难的,随便看看,我嘴笨,直接把url数组链接放进去 打开就可以看, 然后根据注释慢慢了解3分钟就懂了。
  return (
        <>
            //添加事件的大盒子
            <div
                className='box'
                onMouseDown={(e) => mouseDown(e)}
                onMouseMove={(e) => mouseMove(e)}
                onMouseUp={(e) => mouseUp(e)}
                style={{ width: innerWidth, height: innetHeight, overflow: 'hidden' }}>
                //包裹图片的盒子
                <div className='loop' ref={domLoop}>
                //数组的最后一张图片
                    <img src={url[url.length - 1]} ref={domWidth} onMouseDown={(e) => e.preventDefault()} style={{ width: innerWidth, height: innetHeight }} alt="" />
                    {
                        url && url.length > 0 ? url.map((item, index) => {
                            return <img src={item} onMouseDown={(e) => e.preventDefault()} style={{ width: innerWidth, height: innetHeight }} key={index} alt="" />
                        }) : ''
                    }
                    //数组的第一张图片
                    <img src={url[0]} onMouseDown={(e) => e.preventDefault()} style={{ width: innerWidth, height: innetHeight }} alt="" />

                </div>
            </div>


        </>
    )
import React, { useState, useRef, useEffect } from 'react'
import './index.css';


export default function LoopChart(props) {
    const { url, width, height } = props;
    const domWidth = useRef(null);//当前图片宽度
    const domLoop = useRef(null);//图片包裹的盒子 需要对其进行 transform
    const innerWidth = width ? width : '100%';
    const innetHeight = height ? height : '100%';

    const [point, setPoint] = useState(0);//按下
    const [drop, setDrop] = useState(0);//移动  
    const [flag, setFlag] = useState(false);//按键开关 true 关闭transition动画 false 开启动画
    const [global, setGlobal] = useState(0);//数组下标
    const [direction, setDirection] = useState(0); //因为默认有动画 这个作用是取消第一次加载的时候的动画
    // 判断是否传入数组
    useEffect(() => {
        if (url instanceof Array) {

        } else {
            throw ('需传入一个长度大于1的数组!')
        }
    }, [url])

    useEffect(() => {

        if (direction == 0) {
            domLoop.current.style.transition = 'none'
            setDirection(1)
        } else {
            //按键开关 true 关闭transition动画 false 开启动画
            if (flag) {
                domLoop.current.style.transition = 'none'
            } else {
                domLoop.current.style.transition = 'transform 0.2s'
            }
        }


    }, [flag])
    // 4 [ 1, 2, 3, 4] 1
    // 到达数组的临界点, 关闭动画 跳转到 之前手动添加的<img>标签上面
    //如果为1 则在无动画跳转到 array[0]
    //如果是4 则在无动画跳转到 array[ array.length -1 ]
    useEffect(() => {
       
        if (global > url.length - 1) {
            setTimeout(() => {
                domLoop.current.style.transition = 'transform 0s'
                setGlobal(0)
            }, 200);
        }
        if (global < 0) {
            setTimeout(() => {
                domLoop.current.style.transition = 'transform 0s'
                setGlobal(url.length - 1);
            }, 200);
        }
        getLoop()

    }, [global])


    const mouseDown = (e) => {
        setFlag(true)

        setPoint(e.pageX);
    }
    // 手动拖拽的时候 不开启动画 translateX 跟随鼠标移动
    const mouseMove = (e) => {
        if (flag) {

            setDrop(point - e.pageX);

            domLoop.current.style.transform = `translateX(-${domWidth.current.clientWidth + (global * domWidth.current.clientWidth) + drop}px)`

        }

    }
    // 判断是否达到换页标砖
    const mouseUp = (e) => {
        setFlag(false)
        if (domWidth.current.clientWidth / 4 < Math.abs(drop)) {
            if (drop >= 0) {
                setGlobal(global + 1);
            } else {
                setGlobal(global - 1);
            }
        } else {
            getLoop()
        }
        setPoint(0)
        setDrop(0)
    }

    const getLoop = () => {
        domLoop.current.style.transform = `translateX(-${domWidth.current.clientWidth + (global * domWidth.current.clientWidth)}px)`;
    }

    if (url.length < 1 || !url) {

        throw ('最少接收一个长度为1的数组')

    }
    if (url.length == 1) {
        return <img src={url[0]} onMouseDown={(e) => e.preventDefault()} style={{ width: innerWidth, height: innetHeight }} alt='' />
    }

    return (
        <>
            <div
                className='box'
                onMouseDown={(e) => mouseDown(e)}
                onMouseMove={(e) => mouseMove(e)}
                onMouseUp={(e) => mouseUp(e)}
                style={{ width: innerWidth, height: innetHeight, overflow: 'hidden' }}>
                <div className='loop' ref={domLoop}>
                    <img src={url[url.length - 1]} ref={domWidth} onMouseDown={(e) => e.preventDefault()} style={{ width: innerWidth, height: innetHeight }} alt="" />
                    {
                        url && url.length > 0 ? url.map((item, index) => {
                            return <img src={item} onMouseDown={(e) => e.preventDefault()} style={{ width: innerWidth, height: innetHeight }} key={index} alt="" />
                        }) : ''
                    }
                    <img src={url[0]} onMouseDown={(e) => e.preventDefault()} style={{ width: innerWidth, height: innetHeight }} alt="" />

                </div>
            </div>


        </>
    )
}

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐