fix(theme): 用整页快照过渡消除明暗割裂
- 支持 View Transition 时整页旧/新快照交叉淡入 160ms,背景图与底色不再各自过渡 - 不支持或减少动画偏好时回退到原来的颜色过渡
This commit is contained in:
@@ -1422,3 +1422,17 @@ html.theme-transition .site-background {
|
|||||||
grid-template-columns: minmax(0, 1fr);
|
grid-template-columns: minmax(0, 1fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 明暗切换:支持的浏览器直接对整页做快照交叉淡入,避免背景图和底色各变各的 */
|
||||||
|
::view-transition-old(root),
|
||||||
|
::view-transition-new(root) {
|
||||||
|
animation-duration: 160ms;
|
||||||
|
animation-timing-function: var(--su-ease-in-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
::view-transition-old(root),
|
||||||
|
::view-transition-new(root) {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -308,8 +308,26 @@ export default function AppNext() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const root = document.documentElement
|
const root = document.documentElement
|
||||||
if (root.dataset.scheme === scheme) return
|
if (root.dataset.scheme === scheme) return
|
||||||
|
|
||||||
|
const apply = () => {
|
||||||
|
root.dataset.scheme = scheme
|
||||||
|
}
|
||||||
|
const doc = document as Document & {
|
||||||
|
startViewTransition?: (callback: () => void) => unknown
|
||||||
|
}
|
||||||
|
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||||
|
|
||||||
|
if (!reduceMotion && typeof doc.startViewTransition === 'function') {
|
||||||
|
try {
|
||||||
|
doc.startViewTransition(apply)
|
||||||
|
return
|
||||||
|
} catch {
|
||||||
|
// 浏览器正在跑另一段过渡时退回 CSS 过渡
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
root.classList.add('theme-transition')
|
root.classList.add('theme-transition')
|
||||||
root.dataset.scheme = scheme
|
apply()
|
||||||
const timer = window.setTimeout(() => root.classList.remove('theme-transition'), 180)
|
const timer = window.setTimeout(() => root.classList.remove('theme-transition'), 180)
|
||||||
return () => {
|
return () => {
|
||||||
window.clearTimeout(timer)
|
window.clearTimeout(timer)
|
||||||
|
|||||||
Reference in New Issue
Block a user