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

如何实现混沌条状动画效果的主题切换?

如何实现混沌条状动画效果的主题切换?

嗨,我看你已经把圆形主题切换动画做得很流畅了,想要改成混沌条状的效果其实不难,核心还是基于你现在用的View Transition API,只需要把原来的圆形clipPath换成不规则的条状路径就行,我来给你改改代码,顺便解释下思路~

核心思路

原来的圆形动画是通过circle()的clipPath从0半径扩展到全屏,混沌条状效果我们可以用polygon()定义一个不规则的条状初始形状,然后让这个形状逐渐扩展覆盖整个屏幕,模拟那种无序的条状扩散感。如果想要更随机的“混沌”感,还可以每次切换时随机生成初始条状的位置和角度。

修改后的完整代码

HTML部分

<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
  <meta charset="UTF-8">
  <title>Chaotic Strip Theme Toggle</title>
</head>
<body>
<div class="header">
  <button class="toggle-button">Change theme</button>
</div>
<div class="cards"></div>
</body>
</html>

CSS部分(保留你的基础样式,优化了按钮显示)

:root {
    color-scheme: dark;
    --theme-text: white;
    --theme-bg: black;
    --bg-card: #29292d;
    --border-card: #3b3b41;
}

[data-theme="light"] {
    color-scheme: light;
    --theme-text: black;
    --theme-bg: white;
    --bg-card: #dedfe1;
    --border-card: #cacbcc;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
}

body {
    background: var(--theme-bg);
    margin: 0;
    padding: 16px;
}

.header {
    display: flex;
    justify-content: end;
    margin-bottom: 10px;
}

.toggle-button {
    padding: 8px 16px;
    border-radius: 8px;
    border: none;
    cursor: pointer;
    background: var(--bg-card);
    color: var(--theme-text);
}

.cards {
    display: grid;
    gap: 16px;
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.card {
    border: 1px solid var(--border-card);
    color: var(--theme-text);
    background: var(--bg-card);
    border-radius: 14px;
    padding: 6px 10px;
}

JavaScript部分(关键修改动画的clipPath逻辑)

const container = document.querySelector(".cards");

for (let i = 1; i <= 6; i++) {
    const card = document.createElement("div");
    card.className = "card";

    const title = document.createElement("h2");
    title.textContent = `Title${i}`;

    const paragraph = document.createElement("p");
    paragraph.textContent = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

    card.appendChild(title);
    card.appendChild(paragraph);
    container.appendChild(card);
}

document.addEventListener("DOMContentLoaded", () => {
    const btn = document.querySelector(".toggle-button");

    const isDarkMode = () => document.documentElement.getAttribute("data-theme") === "dark";
    const setDarkMode = (enabled) => {
        document.documentElement.setAttribute("data-theme", enabled ? "dark" : "light");
    };

    btn.addEventListener("click", async () => {
        if (!document.startViewTransition || window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
            return setDarkMode(!isDarkMode());
        }

        await document.startViewTransition(() => {
            setDarkMode(!isDarkMode());
        }).ready;

        // 生成随机的条状初始位置,增加混沌感
        const randomY1 = Math.random() * 30 + 35; // 35-65%的垂直位置
        const randomY2 = Math.random() * 30 + 35;
        const stripHeight = 10; // 条状的高度

        document.documentElement.animate(
            {
                clipPath: [
                    // 初始状态:不规则的倾斜窄条
                    `polygon(0% ${randomY1}%, 100% ${randomY2}%, 100% ${randomY2 + stripHeight}%, 0% ${randomY1 + stripHeight}%)`,
                    // 结束状态:全屏覆盖
                    `polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)`
                ],
            },
            {
                duration: 1800,
                easing: "cubic-bezier(0.4, 0, 0.2, 1)", // 更有变化的缓动效果
                pseudoElement: "::view-transition-new(root)",
            }
        );
    });

    setDarkMode(isDarkMode());
});

关键修改点说明

  1. 替换clipPath形状:把原来的circle()换成了polygon(),初始状态是一条随机倾斜的窄条,每次点击都会随机调整条状的位置,让效果更“混沌”;
  2. 调整动画参数:把时长从1500ms改成1800ms,缓动函数换成cubic-bezier(0.4, 0, 0.2, 1),让动画的加速减速更有层次感,不像线性或简单缓动那么规整;
  3. 随机化初始位置:通过Math.random()生成条状的垂直位置,每次切换的初始条状位置都略有不同,增强混沌感;
  4. 优化按钮样式:给按钮加了基础样式,让它在两种主题下都更美观。

如果你想要更夸张的条状效果,还可以尝试用path()定义更复杂的不规则路径,或者同时动画多个条状形状(不过单个多边形的效果已经足够接近你想要的混沌条状了)。

备注:内容来源于stack exchange,提问作者LionLive

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 10:28:04