用 View Transitions 做主题切换水波纹

主题切换时用一个从点击点扩散的圆揭示新主题。半径要够到屏幕最远的角,动画结束必须清掉自定义属性,否则会污染下一次。

深色模式切换是整站唯一一个「整页换色」的瞬时动作,硬切会很突兀。解法是 View Transitions API:把新旧两张快照叠起来,用 clip-path 的圆形裁剪从点击点扩散,揭示新主题。

半径必须够到最远的角

圆心是点击点,半径取它到视口四角的最大距离:

const dx = Math.max(x, innerWidth - x);
const dy = Math.max(y, innerHeight - y);
const radius = Math.hypot(dx, dy);

少算一点,屏幕角落就会留一块旧主题的残角。这个数不能偷懒取「屏幕对角线」:除非点在正中心,斜边永远大于实际需要,动画会在还没覆盖角落时就结束,同样露残角。

把几何交给自定义属性

JS 只负责把圆心与半径写到根元素上,样式侧只读不写:

document.documentElement.style.setProperty('--ripple-x', x + 'px');
document.documentElement.style.setProperty('--ripple-r', radius + 'px');
document.documentElement.dataset.ripple = '1';

结束必须清理

动画结束后删掉 data-ripple 与 --ripple-*。留着的话,下一次切换会带着上一次的圆心与半径开始,看起来像闪一下——这类问题只在第二次点击时出现,最容易漏测。

降级路径

不支持 View Transitions,或用户开了 prefers-reduced-motion,就直接切换主题、不做动画。主题是功能,波纹是装饰,两者不能绑在一起。

← 返回文章列表

评论

…