扇形展开动画需统一 transform-origin: 0 0、反向 rotate 纠偏文字、分开声明 opacity 和 transform 过渡,禁用 transition: all;容器需 relative 定位居中,角度按 i*(360deg/n) 计算,移动端加 touch-action: manipulation 并同步 aria-expanded。

直接用 transform: rotate() + translateX() 配合 transition 就能实现扇形展开的平滑过渡,但必须统一旋转原点、反向纠偏文字、且避免用 transition: all —— 否则动画会卡顿或错位。
扇形定位必须用 transform-origin: 0 0
所有菜单项(li)的旋转中心必须一致,否则每个元素绕自身左上角转,结果是散乱飞出而非沿圆周排列。常见错误是漏设或设成 50% 50%,导致旋转轴偏移。
-
transform-origin: 0 0是硬性要求,写在菜单项基础样式里 - 容器(如
ul)需设position: relative,并居中定位(如top: 50%; left: 50%; transform: translate(-50%, -50%)) - 每项角度 =
i * (360deg / n),其中n是总项数,i从 0 开始计数
translateX() 后必须加反向 rotate() 纠正文字方向
只做 rotate(60deg) translateX(120px),文字会歪着贴在圆弧上;必须再加一层反向旋转,让文字始终朝外或朝上。
- 第
i项完整变换:rotate(${i * angle}) translateX(120px) rotate(${-i * angle}) - 半径值(如
120px)要和容器尺寸匹配,响应式时建议改用vw或rem - 别用
scale()模拟缩放效果——它会放大文字锯齿,且影响点击热区
过渡动画必须分开声明 opacity 和 transform
写 transition: all 0.4s 会导致浏览器重排、文字闪烁,甚至某些浏览器跳过动画。扇形展开本质是两个独立变化:是否可见(opacity)+ 是否到位(transform)。
立即学习“前端免费学习笔记(深入)”;
- 正确写法:
transition: opacity 0.3s, transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275) - 初始状态所有项设为
opacity: 0; transform: rotate(...) translateX(0) - 展开时统一改为
opacity: 1; transform: rotate(...) translateX(120px) rotate(...) - 收起前必须强制 reflow(例如读取
offsetHeight),否则直接移 class 会跳过动画
移动端必须加 touch-action: manipulation
不然 iOS Safari 会在快速连续点击时触发延迟,扇形菜单看起来“点不动”或“反应慢半拍”。
- 加在触发按钮(如
.menu-toggle)和菜单容器上 - 同时确保
aria-expanded和inert属性由 JS 同步控制,否则 VoiceOver 用户无法感知展开状态 - 扇形项太多(>7 个)时,建议降级为线性菜单,避免小屏设备拥挤失效
最易被忽略的是:扇形动画依赖 DOM 渲染顺序与 CSS 计算时机,JS 切换类后如果立即修改 style.transform,反而会打断 CSS 过渡;纯 class 控制才是稳定解法。


















