如何使用frame-motion在动画完成后执行回调

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

我有一个名为 AnimatedText 的组件。当动画完成时,我希望组件用我在 underlineLines prop 中填写的单词加下划线。那么我该怎么做呢?

我尝试过onAnimationEnd功能,但没有带来任何改变

"use client";
import { motion, useInView, Variant, useAnimationControls } from "framer-motion";
import { useEffect, useRef, useState } from "react";

type AnimatedTextProps = {
    text: string | string[];
    el?: keyof JSX.IntrinsicElements;
    className?: string;
    once?: boolean;
    repeatDelay?: number;
    underlineLines?: number[];
    animation?: {
        hidden: Variant;
        visible: Variant;
    };
};

const defaultAnimations = {
    hidden: {
        opacity: 0,
        y: 5,
    },
    visible: {
        opacity: 1,
        y: 0,
        transition: {
            duration: 0.05,
            ease: "easeOut",
        },
    },
};

const AnimatedText = ({ text, el: Wrapper = "p", className, once, repeatDelay, underlineLines, animation = defaultAnimations }: AnimatedTextProps) => {
    const textArray = Array.isArray(text) ? text : [text];
    const controls = useAnimationControls();
    const ref = useRef(null);
    const isInView = useInView(ref, { amount: 0.1, once });
    const [isAnimationEnd, setIsAnimationEnd] = useState(false);

    useEffect(() => {
        let timeout: NodeJS.Timeout;
        const show = () => {
            controls.start("visible");
            if (repeatDelay) {
                timeout = setTimeout(async () => {
                    await controls.start("hidden");
                    controls.start("visible");
                }, repeatDelay);
            }
        };
        isInView ? show() : controls.start("hidden");

        return () => clearTimeout(timeout);
    }, [isInView]);

    return (
        <Wrapper className={className}>
            <span className="sr-only">{textArray.join(" ")}</span>
            <motion.span
                ref={ref}
                initial="hidden"
                animate={controls}
                variants={{
                    visible: { transition: { staggerChildren: 0.05 } },
                    hidden: {},
                }}
                aria-hidden
            >
                {textArray.map((line, lineIndex) => {
                    return (
                        <span className="block" key={`${line}-${lineIndex}`}>
                            {line.split(" ").map((word, wordIndex) => (
                                <span
                                    className={
                                        underlineLines?.includes(wordIndex) && isAnimationEnd
                                            ? "inline-block q-underline q-underline-black q-underline-start"
                                            : "inline-block q-underline q-underline-black"
                                    }
                                    key={`${word}-${wordIndex}`}
                                >
                                    {word.split("").map((char, charIndex) => (
                                        <motion.span
                                            key={`${char}-${charIndex}`}
                                            className={"inline-block"}
                                            variants={animation}
                                            onAnimationEnd={() => {
                                                setIsAnimationEnd(true);
                                            }}
                                        >
                                            {char}
                                        </motion.span>
                                    ))}
                                    <span className="inline-block">&nbsp;</span>
                                </span>
                            ))}
                        </span>
                    );
                })}
            </motion.span>
        </Wrapper>
    );
};

export default AnimatedText;

请帮助我,我已经从许多不和谐服务器中搜索了答案:(

javascript reactjs next.js framer-motion
1个回答
0
投票

您是否正在寻找

onAnimationComplete
<motion.span>
回调?

https://www.framer.com/motion/component/#%23%23onanimationcomplete

© www.soinside.com 2019 - 2024. All rights reserved.