首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何优化拖动动画(useState + transform: transform)

如何优化拖动动画(useState + transform: transform)
EN

Stack Overflow用户
提问于 2022-09-25 16:09:36
回答 1查看 26关注 0票数 0

我有一个卡组件,它可以在移动设备上拖动。在触摸启动时,它保存初始点,在触摸移动时它更新当前点状态,在触摸结束时它恢复点,并使一些逻辑与滑动方向。在台式机上进行测试时,它工作得很好,但在移动平台上却非常敏锐。如何优化拖动动画,使其工作平稳?

如果距离很小,我使用“拖动”键在初始位置平滑重新定位卡。

代码语言:javascript
复制
const Card = ({screens, title, overview, release_date, onSwipe}: props) => {
    const [initialPoint, setInitialPoint] = useState({x: 0, y: 0})
    const [currentPoint, setCurrentPoint] = useState({x: 0, y: 0})
    const [dragging, setDragging] = useState(false)

    const [currentStep, setCurrentStep] = useState(0)

    const touchStartHandler = (e: React.TouchEvent) => {
        setDragging(true)
        setInitialPoint({
            x: e.touches[0].pageX,
            y: e.touches[0].pageY
        })
        setCurrentPoint({
            x: e.touches[0].clientX,
            y: e.touches[0].clientY
        })
    }
    const touchMoveHandler = (e: React.TouchEvent) => {
        setCurrentPoint({
            x: e.touches[0].clientX,
            y: e.touches[0].clientY
        })
    }
    const touchEndHandler = () => {
        if(currentPoint.x - initialPoint.x === 0) {
            if(currentPoint.x > window.screen.width / 2) {if(currentStep < screens.length - 1) setCurrentStep(x => x + 1)}
            else if(currentStep > 0) setCurrentStep(x => x - 1)
        }
        setDragging(false)
        setCurrentPoint({x: 0, y: 0})
    }

    useEffect(() => {
        preload(screens)
    }, [screens])

    return (
        <div
            style={{
                transform: `translate(${currentPoint.x - initialPoint.x}px, ${currentPoint.y - initialPoint.y}px) rotate(${(window.screenX - currentPoint.x + initialPoint.x)/45}deg)`,
transition: dragging ? '0s' : '200ms'
            }}
            onTouchStart={touchStartHandler}
            onTouchMove={touchMoveHandler}
            onTouchEnd={touchEndHandler}
            className={`w-[100%] h-[100%] box-border rounded-2xl absolute overflow-hidden bg-black`}
        >
            <div style={{backgroundImage: `url('${screens[currentStep]}')`}} className={'w-[120%] h-[120%] box-border rounded-2xl bg-black bg-cover bg-center blur-lg absolute left-[-10%] top-[-10%] opacity-50'}/>
            <Stamps currentPoint={currentPoint} initialPoint={initialPoint}/>
            <div className={'bg-contain bg-center bg-no-repeat h-full absolute w-full top-0 rounded-2xl'} style={{backgroundImage: `url('${screens[currentStep]}')`}}/>
            <Counter current={currentStep} total={screens.length}/>
            <div
                className={'bg-rose-100 absolute bottom-0 rounded-2xl w-full text-black p-4'}>
                <div className={'font-bold text-3xl'}>{title}</div>
                <div className={'mt-2 font-medium'}>{release_date.split('-')[0]}, комедия, триллер</div>
                <div className={'leading-4 mt-2 max-h-20 overflow-hidden relative'}>
                    {overview}
                    <div className={'bg-gradient-to-b from-transparent to-rose-100 absolute w-full h-full max-h-20 top-0'}/>
                </div>
                <div className={'text-lg font-medium underline'}>Полностью на themoviedb.org</div>
            </div>
        </div>
    );
};
代码语言:javascript
复制
const Stamps = ({currentPoint, initialPoint}: {currentPoint: point, initialPoint: point}) => {
    return (
        <>
            <div style={{opacity: (currentPoint.x - initialPoint.x - 50) / window.screen.width * 6}}
                 className={'font-bold text-green-400 text-4xl absolute top-28 z-30 border-4 border-green-400 p-4 rounded-2xl rotate-[35deg] left-12'}>НРАВИТСЯ</div>
            <div style={{opacity: (-currentPoint.x + initialPoint.x - 50) / window.screen.width * 6}}
                 className={'font-bold text-red-400 text-4xl absolute top-28 z-30 border-4 border-red-400 p-4 rounded-2xl -rotate-[35deg] right-12'}>НУ ТАКОЕ</div>
            <div style={Math.abs(currentPoint.x - initialPoint.x) < 50 ? {opacity: (-currentPoint.y + initialPoint.y - 50) / window.screen.height * 6} : {opacity: 0}}
                 className={'font-bold text-blue-400 text-4xl absolute bottom-56 z-30 border-4 border-blue-400 p-4 rounded-2xl -rotate-12 right-16'}>ПОСМОТРЮ</div>
            <div style={Math.abs(currentPoint.x - initialPoint.x) < 50 ? {opacity: (currentPoint.y - initialPoint.y - 50) / window.screen.height * 6} : {opacity : 0}}
                 className={'font-bold text-gray-400 text-4xl absolute top-28 z-30 border-4 border-gray-400 p-4 rounded-2xl rotate-12 right-8'}>ПРОПУСТИТЬ</div>
        </>
    );
};
代码语言:javascript
复制
const Counter = ({current, total}: props) => {
    const a = new Array(total).fill(false)
    return (
        <div className={'flex flex-row gap-4 h-5 pt-4 px-4 z-10 absolute top-0 w-full box-border'}>
            {a.map((_, i) => {
                if(i === current) return <div key={`active-${i}`} className={'bg-gradient-to-br from-[#FDABDD] to-[#374A5A] rounded-full flex h-full w-full'}/>
                else return <div key={`passive-${i}`} className={'bg-rose-50 rounded-full flex h-full w-full'}/>
            })}
        </div>
    );
};

此外,一次只显示两张牌。

EN

回答 1

Stack Overflow用户

发布于 2022-09-25 16:19:00

lol,我只是尝试添加到Card类“将-更改-转换”,它将我的动画提升到60 fps。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73845994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档