作为研究的一部分,我将为我的网站实现类似的主题更改。我设法以圆形的形式实现了平滑的主题更改。但我不明白如何以混乱的条带形式进行主题更改,如果您有技能或知识,请告诉我。我附上了我获得的转换的压缩代码,用于紧凑启动。
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 {top, left, width, height} = btn.getBoundingClientRect();
const right = window.innerWidth - left;
const bottom = window.innerHeight - top;
const maxRadius = Math.hypot(Math.max(left, right), Math.max(top, bottom));
document.documentElement.animate(
{
clipPath: [
`circle(0px at ${left + width / 2}px ${top + height / 2}px)`,
`circle(${maxRadius}px at ${left + width / 2}px ${top + height / 2}px)`,
],
},
{
duration: 1500,
easing: "ease-in",
pseudoElement: "::view-transition-new(root)",
}
);
});
setDarkMode(isDarkMode());
});
: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);
}
.header {
display: flex;
justify-content: end;
margin-bottom: 10px;
}
.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;
}
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="header">
<button class="toggle-button">Change theme</button>
</div>
<div class="cards"></div>
</body>
</html>
Clip-path 仅限于简单的形状和多边形,我不确定我是否理解了您所说的“混乱的条带”的意思,但听起来您可以使用 svg 的 stroke-dasharray/stroke-dashoffset 来实现这一点。也许可以尝试使用 svg mask 而不是 clip-path。
编辑:
我为您的演示做了一个小演示,我的 svg 并不完美,但我认为您会调整自己的 svg。我使用 svg 动画制作了 svg(您可以在此处了解更多信息https://www.w3schools.com/graphics/svg_animation.asp )并使用https://yoksel.github.io/url-encoder/将其转换为 data-url 。
我的 SVG:
css 的更改:
我从未使用过 ViewTranstion API,除了使用动画之外,找不到任何其他选项来强制更改伪元素。您还需要为每个 data-url svg 生成新的 id,否则动画可能只会触发一次。脚本更改: