使用两段代码,通过 View Transitions API 为主题切换添加平滑过渡动画

😀 在 Web 开发中,主题切换通常是即时生效的,但这种方式会导致用户视觉上的突兀感。通过 View Transitions API,我们可以实现更流畅的切换动画,让深色模式和浅色模式的过渡更加自然。

功能描述

点击 Switch 组件切换主题时,页面会从点击位置向外扩散,形成类似"水波扩散"的动画效果,使切换过程更具视觉吸引力。

Demo 仓库

核心代码

  1. 主题切换逻辑 在主题切换处理函数中:
ts 复制代码
const handleThemeChange: SwitchProps["onChange"] = (checked: boolean, event) => {
  // 必须加这句
  document.documentElement.className = checked ? "dark" : "light";

  // 获取点击位置,或者回退到页面中间
  const x = event instanceof MouseEvent ? event?.clientX / 2 : innerWidth;
  console.log(x);
  const y = event instanceof MouseEvent ? event?.clientY / 2 : innerHeight;
  // 获取到最远角的距离
  const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
  const circlePath = [`circle(0 at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`];

  // 执行主题切换
  const transition = document.startViewTransition(() => {
    setIsDarkMode(checked);
  });

  // 监听过渡动画的就绪状态
  transition.ready.then(() => {
    document.documentElement.animate(
      {
        clipPath: checked ? circlePath : [...circlePath].reverse(),
      },
      {
        duration: 1000,
        easing: "ease-in",
        pseudoElement: checked ? "::view-transition-new(root)" : "::view-transition-old(root)",
      }
    );
  });
};

document.startViewTransition:执行 dom 更改代码,在 React 中则为发起渲染更新。

transition.ready.then:前后两张快照之间的过渡动画。

  1. 配置全局样式

为了确保 View Transitions 正常工作,需要添加一些 CSS 规则:

css 复制代码
/** Animated Theme Toggle */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

.dark::view-transition-old(root) {
  z-index: 1;
}

.dark::view-transition-new(root) {
  z-index: 999;
}

::view-transition-old(root) {
  z-index: 999;
}

::view-transition-new(root) {
  z-index: 1;
}

总结

  • 核心思路:利用 View Transitions API,通过 clipPath 创建动态扩散动画。
  • 动画细节:根据鼠标点击位置,计算扩散路径,使视觉效果更自然。
  • 兼容性:目前 View Transitions 主要支持 Chrome 111+,其他浏览器支持情况可参考 Can I Use。

这种方式不仅提升了用户体验,还让主题切换更加流畅和现代化。🚀

参考资料

developer.mozilla.org/zh-CN/docs/...

ant.design/index-cn/

相关推荐
招风的黑耳18 分钟前
Web元件库 ElementUI元件库+后台模板页面(支持Axure9、10、11)
前端·elementui·axure
雯0609~19 分钟前
CSS:使用内边距时,解决宽随之改变问题
前端·css
Dolphin_海豚30 分钟前
10 分钟带你入坑 electron
前端·javascript·electron
乐闻x39 分钟前
性能优化:javascript 如何检测并处理页面卡顿
前端·javascript·性能优化
雯0609~1 小时前
vue3:八、登录界面实现-忘记密码
前端·javascript·vue.js
烂蜻蜓1 小时前
深入理解 HTML 中的<div>和元素:构建网页结构与样式的基石
开发语言·前端·css·html·html5
木木黄木木1 小时前
HTML5 Canvas弹跳小球游戏开发实战与技术分析
前端·html·html5
Anlici2 小时前
Axios 是基于 Ajax 还是 Fetch?从源码解析其实现
前端·面试
一个处女座的程序猿O(∩_∩)O2 小时前
Vue 中的 MVVM、MVC 和 MVP 模式深度解析
前端·vue.js·mvc
鱼樱前端2 小时前
前端程序员集体破防!AI工具same.dev像素级抄袭你的代码,你还能高傲多久?
前端·javascript·后端