我尝试建立一个简单的图像carpet的帮助下,帧运动。
我想使用按钮和拖动来控制幻灯片。它工作得很好,但是当我超过最后一张幻灯片上的滑块时,它会动画回到开始,并完全打乱索引逻辑。
下面是我的代码:
"use client";
import { useState } from "react";
import { AnimatePresence, motion, MotionConfig, PanInfo } from "framer-motion";
let images = [
"/images/carousel/1.jpeg",
"/images/carousel/2.jpeg",
"/images/carousel/3.jpeg",
"/images/carousel/4.jpeg",
"/images/carousel/5.jpeg",
];
export default function App() {
let [index, setIndex] = useState(0);
const dragEndHandler = (dragInfo: PanInfo) => {
const draggedDistance = dragInfo.offset.x;
const swipeThreshold = 50;
if (draggedDistance > swipeThreshold) {
console.log("swipe detection: ", "prev");
index > 0 && setIndex(index - 1);
} else if (draggedDistance < -swipeThreshold) {
console.log("swipe detection: ", "next");
index + 1 < images.length && setIndex(index + 1);
}
};
return (
<MotionConfig transition={{ duration: 0.7, ease: [0.32, 0.72, 0, 1] }}>
<div className="relative overflow-hidden">
<motion.div
animate={{ x: `-${index * 100}%` }}
className="flex"
drag="x"
dragElastic={1}
dragConstraints={{ left: 0, right: 0 }}
onDragEnd={(_, dragInfo: PanInfo) => dragEndHandler(dragInfo)}
>
{images.map((image) => (
<div className="aspect-[4/5] w-full min-w-full">
<img
key={image}
src={image}
className="object-cover min-w-full pointer-events-none"
/>
</div>
))}
</motion.div>
<AnimatePresence initial={false}>
{index > 0 && (
<motion.button
initial={{ opacity: 0 }}
animate={{ opacity: 0.7 }}
exit={{ opacity: 0, pointerEvents: "none" }}
whileHover={{ opacity: 1 }}
className="absolute left-2 top-1/2 -mt-4 flex h-8 w-8 items-center justify-center rounded-full bg-white"
onClick={() => setIndex(index - 1)}
>
<div className="h-6 w-6">Prev</div>
</motion.button>
)}
</AnimatePresence>
<AnimatePresence initial={false}>
{index + 1 < images.length && (
<motion.button
initial={{ opacity: 0 }}
animate={{ opacity: 0.7 }}
exit={{ opacity: 0, pointerEvents: "none" }}
whileHover={{ opacity: 1 }}
className="absolute right-2 top-1/2 -mt-4 flex h-8 w-8 items-center justify-center rounded-full bg-white"
onClick={() => setIndex(index + 1)}
>
<div className="h-6 w-6">Next</div>
</motion.button>
)}
</AnimatePresence>
</div>
</MotionConfig>
);
}
字符串
我尝试使用dragSnapToOrigin={false}
,但这不与弹性等工作.我认为问题发生从弹性的使用和我如何确定拖动方向.但我不能解决这个问题在这里.任何帮助将不胜感激:)
1条答案
按热度按时间fruv7luv1#
这个问题来自于你的
motion.div
的宽度,它是dragConstraints
。我给你的motion.div
添加了一些边框,注意到它只有一张幻灯片宽。这导致dragConstraints
不能像你期望的那样工作。当你到达旋转木马的末尾并向右拖动时,约束启动并将转换样式重置为“无”,所以我们看到carousel缩放回第一张幻灯片,即使索引没有改变。在我使用framer motion的经验中,我最成功地让dragContraints
按照我认为他们应该的方式行事,通过使用ref而不是设置top
,left
等。这些是需要更新以获得所需结果的内容:
1.更改
dragConstraints
以使用附加到父容器的引用。1.确保幻灯片容器的宽度等于所有幻灯片宽度的总和。如果我们希望每张幻灯片都是幻灯片容器宽度的100%,则幻灯片容器的宽度需要为
(images.length * 100)%
。1.将容器的
x
偏移量更新为一个图像的宽度(100 / images.length)%
乘以索引。1.从幻灯片中删除
min-w-full
类。下面是我创建的this working example的相关代码片段。
字符串