React 旋转木马自定义变换(不是水平/垂直)

问题描述 投票:0回答:0

我是 ReactJS 和轮播的初学者。我想编写一个看起来像这样的旋转木马,自动旋转:

我想我了解轮播的一般做法:

  • 创建包含对象的
    data
    数组;
  • 导出一个组件,将
    data
    data.map((obj, index) => (...))
    )的每个元素映射到一个HTML元素;
  • 向组件添加状态变量
    slideInd
    ,它将表示数组第 0 个元素的
    margin-left
    CSS 属性的值
    data
    ;
  • 使用
    useEffect
    钩子触发更新第 0 个数组元素的
    margin-left
    CSS 属性的状态,创建向左滑动的效果(尽管它只是修改第 0 个元素的状态);
  • 在同一个
    useEffect
    setTimeout()
    函数中,如果你的状态已经达到
    data
    数组的长度,确保循环回到第0个元素;

例如,

import { v4 as uuidv4 } from "uuid";
import styled from "@emotion/styled"
import { useState, useEffect } from "react";

const Wrapper = styled.div`
    display: flex;
    overflow-x: visible;
`;

const Slide = styled.div`
    width: 100%;
    flex-shrink: 0;
    outline: 3px solid green;
    transition: all 1s ease-in-out;
    display: flex;
    justify-content: center;
    align-items: center;
    &::before{
        content: "";
        min-height: 100px;
    }
`

const data = [
    {'id': uuidv4(), 'title': 'slide1'},
    {'id': uuidv4(), 'title': 'slide2'},
    {'id': uuidv4(), 'title': 'slide3'},
]

const Test = ({ ...props }) => {   

    const [slideInd, setSlideInd] = useState(0)

    useEffect(() => {
        const timeout = setTimeout(() => {
            // If at the end, scroll all the way back to the beginning
            // ideal function: go back one step at a time instead
            const n = slideInd >= data.length - 1 ? 0 : slideInd + 1
            setSlideInd(n)
            console.log(`Rotate margin left 0th element by: -${slideInd*100}%`)
        // Here, "2000" is the delay miliseconds that the timer waits
        // before the "timeout" function is executed -- this is the
        // miliseconds before each slide "slides"
        }, 2000)
        // Clear the timeout to avoid any memory leaks
        return () => clearTimeout(timeout)
    }, [slideInd])

    return (
        <Wrapper {...props}>
            {data.map((obj, index) => (
                <Slide 
                    style={{
                        marginLeft: index === 0 ? `-${slideInd * 100}%` : undefined,
                    }}
                    // Each child in a list should have a unique "key" prop
                    key={obj.id}
                >
                    {obj.title}
                </Slide>
            ))}
        </Wrapper>
    )
}

export default Test

编辑:尝试回答

如果我尝试改变它来实现我的想法,我想:

  • 不是使用控制 CSS 属性
    margin-left
    的索引,而是改变
    data
    数组的状态本身
  • useEffect
    中,通过将第一个元素放到最后一个位置来更新
    data
import { v4 as uuidv4 } from "uuid";
import styled from "@emotion/styled"
import { useState, useEffect } from "react";

const Wrapper = styled.div`
    display: flex;
    overflow-x: visible;
    justify-content: center;
    align-items: center;
`;

const Slide = styled.div`
    flex-shrink: 0;
    outline: 3px solid green;
    transition: all 1s ease-in-out;
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 520px;
    background: rgba(255, 255, 255, 0.7);
    &::before{
        content: "";
        min-height: 330px;
    }
`

const Test = ({ ...props }) => {   
    
    const [data, setData] = useState([
        {'id': uuidv4(), 'title': 'slide1', 'p': 1},
        {'id': uuidv4(), 'title': 'slide2', 'p': 3},
        {'id': uuidv4(), 'title': 'slide3', 'p': 5},
    ])

    useEffect(() => {
        const timeout = setTimeout(() => {
            // Push first element to end of array
            let el = data.shift()
            data[data.length] = el
            setData([...data])
        }, 3600)
        // Clear the timeout to avoid any memory leaks
        return () => clearTimeout(timeout)
    }, [data])
    

    return (
        <Wrapper {...props}>
            {data.map((obj, index) => (
                <Slide 
                    style={{
                        marginLeft: `${index}%`,
                        marginTop: `-${index}%`,
                        zIndex: -index,
                    }}
                    // Each child in a list should have a unique "key" prop
                    key={obj.id}
                >
                    {obj.title}
                </Slide>
            ))}
        </Wrapper>
    )
}

export default Test

这确实不断地旋转数组的元素,但它缺少:

  • 流畅的过渡:元素在每个事件周期从页面中心重新动画;

有没有办法在不必更新

data
数组本身的值的情况下实现这种混洗效果?

谢谢!!

reactjs next.js carousel
© www.soinside.com 2019 - 2024. All rights reserved.