You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GSAP滑块文本进出动画实现求助(附完整代码)

实现GSAP滑块文本的退出与进入动画

你需要在幻灯片切换时为文本添加独立的动画效果,以下是修改后的代码及关键说明:

核心修改点

  1. 初始化文本入场动画:在init函数中为第一张幻灯片的文本添加初始入场动画,提升内容层次感。
  2. 切换时的文本动画:在slideAnimation函数中同步处理当前幻灯片文本的退出动画与新幻灯片文本的进入动画,和幻灯片位移动画配合执行。
  3. 状态重置:每次切换前重置所有文本元素的动画属性,避免属性累积导致异常。

修改后的完整代码

JavaScript部分

console.clear(); // Just for codepen clear the console between refreshes
// gsap.registerPlugin(SplitText, Draggable);
document.querySelectorAll(".slider").forEach((container) => {
    // Setup variables
    const items = container.querySelectorAll(".slider__wrraper"),
        itemsMax = items.length - 1;
    const next = container.querySelector(".next"),
        prev = container.querySelector(".prev"),
        dots = container.querySelector(".slider_dots");
    let index = 0;
    const move = 100;
    const timer = 5000;
    const duration = 0.5;
    // let autoplay;
    //--------------------------------//
    // 💾 Inital setup
    //--------------------------------//
    function init() {
        // Create 🟣 Dots
        items.forEach((item, index) => {
            const dot = document.createElement("li");
            if (index === 0) dot.classList.add("active"); // Set the first dot to active
            // Allow clicking the dots
            dot.addEventListener("click", () => {
                slideLogic(false, index);
            });

            if (dots) dots.appendChild(dot);
        });
        // Animate the first element in
        gsap.set(items, { autoAlpha: 0 });
        gsap.set([".slider", items[index]], { autoAlpha: 1 });
        // 为第一张幻灯片的文本添加入场动画
        gsap.from([items[index], items[index].querySelector('.slider__context')], { 
            autoAlpha: 0, 
            x: move, 
            y: 30,
            stagger: 0.1,
            duration: duration
        });
        // autoplay = window.setTimeout(slideLogic, timer);
    }
    // Run inital setup
    init();
    // END 💾 Inital setup --------------//

    //--------------------------------//
    // ☝️ Touch
    //--------------------------------//
    if (window.Draggable) {
        Draggable.create(items, {
            type: "x", // Drag only on the X axis
            zIndexBoost: false,
            onDragStart: function () {
                // window.clearTimeout(autoplay); // disable autoplay
                slideLogic(this.getDirection() === "right" ? true : false);
            }
        });
    }
    // END ☝️ Touch  --------------//

    //--------------------------------//
    // Set active 🟣 dot
    //--------------------------------//
    function dotActive(index) {
        const dotsAll = dots.querySelectorAll("li");
        dotsAll.forEach((dot) => {
            dot.classList.remove("active");
        });
        dotsAll[index].classList.add("active");
    }
    // END Set active 🟣 dot --------------//

    //--------------------------------//
    // 🖼️ Slide animation
    //--------------------------------//
    function slideAnimation(index, moveIn, outIn) {
        // Reset the properties you are animating below
        // Otherwise they animate from that position (probably not visible)
        gsap.set(items, { xPercent: 0, scale: 1 });
        gsap.set(items[moveIn], { autoAlpha: 1 });
        // 重置所有文本元素的状态
        gsap.set([...items.map(item => item.querySelector('.slider__context'))], { y: 0, autoAlpha: 1 });

        // 获取当前和新幻灯片的文本元素
        const currentText = items[index].querySelector('.slider__context');
        const newText = items[moveIn].querySelector('.slider__context');

        // The animation
        const tl = gsap.timeline({
            defaults: {
                duration: duration
            },
            onStart: animationStart,
            onComplete: animationDone,
        });
        // 当前幻灯片退出:文本先淡出上移,同步幻灯片位移
        tl.to([items[index], currentText], { 
            xPercent: outIn[0],
            y: -30,
            autoAlpha: 0,
            stagger: 0.1
        });
        // 新幻灯片进入:幻灯片位移同步文本淡入下移
        tl.from([items[moveIn], newText], { 
            xPercent: outIn[1],
            y: 30,
            autoAlpha: 0,
            stagger: 0.1
        }, "<");
        // Hide moved out slide
        tl.set(items[index], { autoAlpha: 0, y: 0 });
    }
    function animationStart() {
        container.classList.add("running");
    }
    function animationDone() {
        toggleButtons();
        // autoplay = window.setTimeout(slideLogic, timer);
        container.classList.remove("running");
        gsap.set(items, { x: 0 });
    }
    // END 🖼️ Slide animation --------------//

    //--------------------------------//
    // Slider 🎛️ logic
    //--------------------------------//
    function slideLogic(prev, customMoveIn) {
        toggleButtons(); // Disable buttons
        // window.clearTimeout(autoplay); // disable autoplay
        let outIn = [-move, move];
        if (prev) outIn.reverse();
        let moveIn;
        // Check if moveIn is passed with the function
        if (typeof customMoveIn === "undefined") {
            if (prev) {
                moveIn = index === 0 ? itemsMax : index - 1;
            } else {
                moveIn = index === itemsMax ? 0 : index + 1;
            }
        } else {
            moveIn = customMoveIn;
        }
        if (dots) dotActive(moveIn); // Set active dot
        slideAnimation(index, moveIn, outIn); // Animation function
        // Changing the next index
        if (typeof customMoveIn === "undefined") {
            if (prev) {
                index === 0 ? (index = itemsMax) : index--;
            } else {
                index === itemsMax ? (index = 0) : index++;
            }
        } else {
            index === itemsMax ? (index = 0) : (index = customMoveIn);
        }
    }
    // END Slider 🎛️ logic --------------//

    //--------------------------------//
    // Button 🎛️ control
    //--------------------------------//
    function toggleButtons() {
        if (next) next.disabled = !next.disabled;
        if (prev) prev.disabled = !prev.disabled;
    }
    if (next) next.addEventListener("click", () => slideLogic());
    if (prev) prev.addEventListener("click", () => slideLogic(true));
    // END Button 🎛️ control --------------//
});

CSS和HTML部分保持不变

动画说明

  • 退出动画:当前幻灯片文本伴随幻灯片位移,同时向上移动30px并淡出,形成连贯退场效果。
  • 进入动画:新幻灯片文本伴随幻灯片位移,同时从下方30px位置淡入,增强内容层次感。
  • Stagger效果:使用stagger: 0.1让幻灯片与文本动画产生0.1秒延迟,使动画更自然流畅。

你可根据需求调整动画参数(如y轴偏移量、stagger延迟时间、动画时长等),匹配自身设计风格。

内容的提问来源于stack exchange,提问作者Adesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 07:45:52