我有一个卡组件,它可以在移动设备上拖动。在触摸启动时,它保存初始点,在触摸移动时它更新当前点状态,在触摸结束时它恢复点,并使一些逻辑与滑动方向。在台式机上进行测试时,它工作得很好,但在移动平台上却非常敏锐。如何优化拖动动画,使其工作平稳?
如果距离很小,我使用“拖动”键在初始位置平滑重新定位卡。
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>
);
};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>
</>
);
};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>
);
};此外,一次只显示两张牌。
发布于 2022-09-25 16:19:00
lol,我只是尝试添加到Card类“将-更改-转换”,它将我的动画提升到60 fps。
https://stackoverflow.com/questions/73845994
复制相似问题