reactjs - 我想在按下按钮时减慢 Box 的动画
问题描述
我正在使用 react.js、Typescript、脉轮和动画成帧器。有一个 MotionSwipe 组件可以让你左右滑动。可以拖动它来滑动子元素的 Box。我们希望 Box 不仅可以通过拖动,还可以通过按下按钮来向右或向左移动。在按下按钮时调用的 onClickSwipe 函数中,我执行了 animateCardSwipe 函数以使其向右滑动。但是,动画太快了,我看不到。当按下按钮时,我想减慢 Box 向右移动的动画。
import { Button,Box } from '@chakra-ui/react';
import { PanInfo, useMotionValue, useTransform } from 'framer-motion';
import { NextPage } from 'next';
import { MotionSwipe } from 'components/MotionSwipe';
import React, { useState } from 'react';
const Component: React.VoidFunctionComponent = () => {
const [cards, setCards] = useState([
{ text: 'Up or down', background: 'red' },
{ text: 'Left or right', background: 'green' },
{ text: 'Swipe me!', background: 'gray' },
]);
const [dragStart, setDragStart] = useState<{ axis: string | null; animation: { x: number; y: number } }>({
axis: null,
animation: { x: 0, y: 0 },
});
const x = useMotionValue(0);
const y = useMotionValue(0);
const onDirectionLock = (axis: string | null) => setDragStart({ ...dragStart, axis: axis });
const animateCardSwipe = (animation: { x: number; y: number }) => {
setDragStart({ ...dragStart, animation });
setTimeout(() => {
setDragStart({ axis: null, animation: { x: 0, y: 0 } });
x.set(0);
y.set(0);
setCards([...cards.slice(0, cards.length - 1)]);
}, 200);
};
const onDragEnd = (info: PanInfo) => {
if (dragStart.axis === 'x') {
if (info.offset.x >= 400) animateCardSwipe({ x: 300, y: 0 });
else if (info.offset.x <= -400) animateCardSwipe({ x: -300, y: 0 });
} else {
if (info.offset.y >= 100) animateCardSwipe({ x: 0, y: 100 });
else if (info.offset.y <= -100) animateCardSwipe({ x: 0, y: -100 });
}
};
const rotate = useTransform(x, [-700, 700], [-90, 90]);
const onClickSwipe = () => {
animateCardSwipe({ x: 500, y: 0 });
};
return (
<>
<Box display="flex" justifyContent="center" width="300px">
{cards.map((card, index) =>
index === cards.length - 1 ? (
<MotionSwipe
animate={dragStart.animation}
card={card}
key={index}
onDirectionLock={(axis: string) => onDirectionLock(axis)}
onDragEnd={(e: MouseEvent, info: PanInfo) => onDragEnd(info)}
style={{ x, y, zIndex: index, rotate: rotate }}
>
<Box background={card.background} height="300px" width="300px"></Box>
</MotionSwipe>
) : (
<MotionSwipe
card={card}
key={index}
style={{
zIndex: index,
}}
>
<Box background={card.background} height="300px" width="300px"></Box>
</MotionSwipe>
),
)}
</Box>
<Button onClick={onClickSwipe}>
○
</Button>
<Button>✖︎</Button>
</>
);
};
const SwipeBox: NextPage = () => {
return <Component />;
};
export default SwipeBox;
interface Props {
animate?: { x: number; y: number };
onDirectionLock?: (axis: 'x' | 'y') => void;
onDragEnd?: (e: MouseEvent, info: PanInfo) => void;
style: { x?: MotionValue; y?: MotionValue; zIndex: number; rotate?: MotionValue };
card: { text: string; background: string };
}
export const MotionSwipe: React.FunctionComponent<Props> = (props) => {
return (
<MotionBox
animate={props.animate}
background="white"
borderTopRadius="8px"
className="card"
display="grid"
drag
dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0 }}
dragDirectionLock
left={0}
onDirectionLock={props.onDirectionLock}
onDragEnd={props.onDragEnd}
placeItems="center center"
position="absolute"
style={{ ...props.style }}
top={0}
transition={{ ease: [0.6, 0.05, -0.01, 0.9], duration: 3 }}
>
{props.children}
</MotionBox>
);
};
解决方案
是的,当它快速移动时没关系。如何改变:
- 设置
useState
变量以检查按钮是否被按下。例如:const [pressed, setPressed] = useState(false);
- 如果按钮被按下,你设置
setPressed(true)
- 如果
pressed(true)
你用.transition
_animation
duration
如果您没有duration
,您的元素将在按钮单击后立即触发。
推荐阅读
- templates - 是否可以在大豆(闭包模板)中连接两个字符串?
- javascript - 使用 onchange 事件挂钩自动保存编辑器注释
- ios - IBoutlet 如何保持初始值较弱?意味着其他一些强大的物体正在指向?
- python-3.x - 如何从包含带空格的字符串的文本文件中创建列?
- android - 尝试使用改造 android 使用发布请求和响应,但无法将 org.json.JSONObject$1 之类的错误转换为 JSONArray
- haskell - 如何在haskell的列表中存储高阶函数数据?
- c++ - 为什么 std::call_once 在加入和分离线程中表现不同?
- sql-server - 如何在链接服务器中运行选择查询
- xamarin.forms - Xamarin iOS 搜索栏自定义
- python - imread 在 Spyder 中有效,但在 VS Code 中无效