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

JavaScript步骤进度条仅首次点击过渡动画正常问题求助

问题解决:步骤进度条描述切换动画失效及优化方案

问题原因

动画仅首次生效的核心原因是:动画类(leave-left/leave-right/enter-left/enter-right)在第一次执行后未被彻底移除。第二次点击步骤时,目标元素仍保留这些类名,浏览器不会重复触发相同的动画规则,导致过渡效果消失。

你手动移除类的思路是正确的,只需确保类的移除与重新添加之间存在DOM更新间隙,让浏览器识别状态变化以重新触发动画。

解决方案

在updateProgress函数中,先清除所有动画类,再通过requestAnimationFrame延迟添加新动画类,确保DOM完成状态更新后触发动画:

const updateProgress = () => {
    // 清除所有动画类
    texts.forEach(text => {
        text.classList.remove("leave-left", "leave-right", "enter-left", "enter-right");
    });

    // 更新步骤激活状态
    steps.forEach((step, i) => {
        step.classList.toggle("active", i < active);
    });

    // 更新文本激活状态
    texts.forEach((text, i) => {
        text.classList.toggle("active", (i + 1) === active);
    });

    // 延迟添加动画类,确保DOM状态更新完成
    requestAnimationFrame(() => {
        if (!previous) return; // 首次加载无previous,跳过动画
        const prevText = texts[previous - 1];
        const currentText = texts[active - 1];

        if (previous > active) {
            prevText.classList.add("leave-right");
            currentText.classList.add("enter-left");
        } else if (previous < active) {
            prevText.classList.add("leave-left");
            currentText.classList.add("enter-right");
        }
    });
};

整体代码优化方案

1. 简化事件绑定(消除重复代码)

无需为每个步骤单独绑定点击事件,通过循环遍历steps集合,利用data-index属性存储步骤索引:

修改HTML:

<ul id="progress-bar">
    <li class="step step-1 active" data-index="1">One</li>
    <li class="step step-2" data-index="2">Two</li>
    <li class="step step-3" data-index="3">Three</li>
    <li class="step step-4" data-index="4">Four</li>
    <li class="step step-5" data-index="5">Five</li>
</ul>

统一绑定事件:

steps.forEach(step => {
    step.addEventListener("click", () => {
        previous = active;
        active = parseInt(step.dataset.index);
        updateProgress();
    });
});

2. 简化激活状态判断

用classList.toggle()替代复杂条件判断,代码更简洁:

// 更新步骤激活状态
steps.forEach((step, i) => {
    step.classList.toggle("active", i < active);
});

// 更新文本激活状态
texts.forEach((text, i) => {
    text.classList.toggle("active", (i + 1) === active);
});

3. 优化动画逻辑

避免重复遍历texts集合,直接通过索引获取上一个和当前文本元素,减少不必要的循环:

// 延迟触发动画
requestAnimationFrame(() => {
    if (!previous) return;
    const prevText = texts[previous - 1];
    const currentText = texts[active - 1];

    if (previous > active) {
        prevText.classList.add("leave-right");
        currentText.classList.add("enter-left");
    } else if (previous < active) {
        prevText.classList.add("leave-left");
        currentText.classList.add("enter-right");
    }
});

4. 修复CSS冗余过渡属性

补充缺失的过渡时长,确保过渡效果明确:

#progress-bar li.active:before {
    border-color: #b78e15;
    background-color: #b78e15;
    transition: all .8s; /* 补充时长,与hover效果保持一致 */
}

#progress-bar li.active:after {
    background-color: #b78e15;
    transition: all .8s; /* 补充时长 */
}

完整优化后的JS代码

const steps = document.querySelectorAll(".step");
const texts = document.querySelectorAll(".progress-text");
let active = 1;
let previous;

const updateProgress = () => {
    // 清除所有动画类
    texts.forEach(text => {
        text.classList.remove("leave-left", "leave-right", "enter-left", "enter-right");
    });

    // 更新步骤激活状态
    steps.forEach((step, i) => {
        step.classList.toggle("active", i < active);
    });

    // 更新文本激活状态
    texts.forEach((text, i) => {
        text.classList.toggle("active", (i + 1) === active);
    });

    // 延迟触发动画
    requestAnimationFrame(() => {
        if (!previous) return;
        const prevText = texts[previous - 1];
        const currentText = texts[active - 1];

        if (previous > active) {
            prevText.classList.add("leave-right");
            currentText.classList.add("enter-left");
        } else if (previous < active) {
            prevText.classList.add("leave-left");
            currentText.classList.add("enter-right");
        }
    });
};

// 统一绑定点击事件
steps.forEach(step => {
    step.addEventListener("click", () => {
        previous = active;
        active = parseInt(step.dataset.index);
        updateProgress();
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 10:27:27