UI 动效参数联调
前端开发在对接设计师的动效标注时,发现设计师给的 cubic-bezier(0.68, -0.55, 0.27, 1.55) 在代码里弹跳过于剧烈。手动调贝塞尔手柄像猜谜,每改一个点就要重新打包预览。在本工具里拖拽曲线控制点,实时看元素位移轨迹,找到弹跳幅度更柔和的 (0.34, 1.56, 0.64, 1) 组合,把参数直接复制进 CSS,省去 6 轮构建-刷新循环。
时间轴空白处点击新增停靠点 · 拖拽菱形改 % · 双击删除 · 0% / 100% 不可删
为一个 CSS 动画调缓动曲线,往往要在开发者工具里反复试,或者凭感觉写 cubic-bezier 参数。这个工具把 keyframes 的关键帧和缓动函数变成可视拖拽,每调一个手柄,动画预览即时更新——不用猜 0.42-0-0.58-1 到底长什么样。所有计算在浏览器本地完成,动画参数不会上传服务器。
前端开发在对接设计师的动效标注时,发现设计师给的 cubic-bezier(0.68, -0.55, 0.27, 1.55) 在代码里弹跳过于剧烈。手动调贝塞尔手柄像猜谜,每改一个点就要重新打包预览。在本工具里拖拽曲线控制点,实时看元素位移轨迹,找到弹跳幅度更柔和的 (0.34, 1.56, 0.64, 1) 组合,把参数直接复制进 CSS,省去 6 轮构建-刷新循环。
产品经理要求复刻竞品 App 的「微光呼吸」脉冲动画,但对方用了私有缓动库。录屏逐帧拆解后发现,动画在 0-30% 阶段加速极快、后段极慢。在本工具里用预设的 easeInOutBack 做基底,再微调弹簧阻尼系数和过冲量,直到模拟出的位移-时间曲线与录屏帧数据重合。最终得到一组 5 个关键帧的百分比-透明度映射表,直接写入 Lottie JSON。
七夕 H5 的翻页转场在低端机上掉帧严重,原因是用了 8 个关键帧的 opacity 和 transform 同时变化。在本工具里拆解动画序列,发现第 3-4 帧之间 opacity 从 0 跳到 1 与 scale 从 0.8 缩到 0.6 的起始时刻重合,造成一次重排。通过调整关键帧偏移量,让两个属性错开 150ms 触发,并降低 scale 变化幅度,最终在 Redmi 9A 上稳定 40fps。
设计师交付了一个复杂的 SVG 路径形变动画,要求从圆形渐变为五角星再变回圆形。手动计算 12 个控制点的 stroke-dasharray 和 d 属性变化量需要大量试错。在本工具里导入 SVG 路径,逐帧拖拽锚点,工具自动补全中间帧的路径坐标差值,导出可直接粘贴到 <animate> 标签的 values 属性中,把 40 分钟的调参压缩到 8 分钟。
物理老师做「简谐运动」课件,需要展示弹簧振子从最大位移到平衡位置再返回的连续运动,并标注每个时刻的速度方向。用本工具创建 20 个关键帧,每帧绑定一个三角函数计算出的位移值,在时间轴上拖动帧位置微调节奏。导出为 CSS steps() 动画,嵌入 PowerPoint 后按空格键逐帧播放,学生能清晰看到每个相位点的速度矢量变化。
| 输入 | 输出 | 说明 |
|---|---|---|
| { "opacity": [0, 1], "transform": ["translateX(0px)", "translateX(100px)"] } | 生成 4 个关键帧:0% { opacity: 0; transform: translateX(0px); } 50% { opacity: 0.5; transform: translateX(50px); } 100% { opacity: 1; transform: translateX(100px); } | 常规:双属性同时动画,验证工具能自动插值生成中间帧,且默认缓动为 ease |
| { "background-color": ["#ff0000", "#0000ff"] } | 生成 2 个关键帧:0% { background-color: #ff0000; } 100% { background-color: #0000ff; } | 常规:颜色值动画,验证工具支持十六进制颜色插值,输出仅首尾帧(因用户未指定中间帧数量) |
| { "width": ["100px", "200px"] } | 生成 2 个关键帧:0% { width: 100px; } 100% { width: 200px; } | 边界:仅 2 个值且无百分比指定,工具默认生成 0% 和 100% 两个关键帧,不自动插入中间帧 |
| { "opacity": [0, 1, 0] } | 生成 3 个关键帧:0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0; } | 边界:3 个值自动等分时间轴(0%、50%、100%),验证工具对数组长度 > 2 的等分逻辑 |
| { "transform": ["rotate(0deg)", "rotate(360deg)"] } | 生成 2 个关键帧:0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } | 易错:用户可能预期自动生成多帧形成旋转动画,但工具仅输出首尾帧,实际动画由浏览器插值完成 |
| { "opacity": [0.5] } | 错误:至少需要 2 个值才能生成关键帧动画 | 易错:只传单个值无法构成动画,工具应明确报错而非静默失败 |
| { "margin": ["10px", "20px"] } | 生成 2 个关键帧:0% { margin: 10px; } 100% { margin: 20px; } | 边界:简写属性(margin)支持,验证工具能处理 CSS 简写属性名 |
1.缓动函数名拼写错误,导致动画不生效
animation-timing-function: ease-outt;animation-timing-function: ease-out;CSS 标准中缓动函数名是大小写敏感的预定义关键字,拼写错误(如多一个 t)会被浏览器忽略,回退为默认的 ease。
2.cubic-bezier 参数超出 [0,1] 范围,产生不可控弹跳
cubic-bezier(2, 0.5, -1, 0.3)cubic-bezier(0.68, -0.55, 0.27, 1.55)cubic-bezier 的 P1、P2 的 x 值必须在 [0,1] 内(时间轴约束),y 值可超出。但 x 超出会导致动画时间非单调,浏览器可能忽略或截断。
3.keyframes 百分比顺序混乱,浏览器只认最后一个相同位置
@keyframes move { 100% { left: 0; } 50% { left: 100px; } }@keyframes move { 0% { left: 0; } 50% { left: 100px; } 100% { left: 200px; } }CSS 规范要求 keyframes 按百分比升序解析,但浏览器遇到重复或乱序的百分比时,只保留最后出现的定义,导致中间状态丢失。
4.animation 简写属性顺序颠倒,部分值被忽略
animation: 2s slidein ease-in 1s infinite;animation: slidein 2s ease-in 1s infinite;animation 简写中第一个时间值被当作 duration,第二个才是 delay。若把 name 放首位,浏览器会尝试解析为 duration 导致失败,name 被忽略。
5.steps() 函数中 start/end 参数写错,动画首帧跳跃
animation-timing-function: steps(4, start); /* 期望渐变出现 */animation-timing-function: steps(4, end);steps(start) 在每一帧开始时立即跳转,适合闪烁效果;steps(end) 在帧结束时跳转,适合平滑逐帧动画。选错会导致首帧或末帧视觉跳跃。
6.animation-fill-mode 未设置,动画结束后元素回退到初始状态
animation: fadeOut 1s; /* 动画结束后元素又显示 */animation: fadeOut 1s forwards;默认 fill-mode 为 none,动画结束后元素回到 keyframes 0% 或原始样式。设置 forwards 可保留最后一帧(100%)的样式。
7.百分比关键帧中漏写 transform 属性,导致覆盖而非叠加
@keyframes rotate { 0% { transform: rotate(0deg); } 100% { rotate: 360deg; } }@keyframes rotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }CSS 中 rotate 是独立属性(新规范),与 transform 不互通。若混用,浏览器会分别处理,最终只应用一个,导致动画失效。
8.animation-direction 与 iteration-count 组合误解,产生意外反向
animation: bounce 1s ease infinite alternate; /* 期望一直正向 */animation: bounce 1s ease infinite normal;alternate 会让动画在奇数次正向、偶数次反向播放。若期望始终同向,应显式设为 normal(默认值),否则视觉上会来回倒放。
p(t) = t³ (10 - 15t + 6t²)
t归一化时间,0 到 1 之间p(t)缓动后的进度值,0 到 1动画时长 2 秒,当前时间 0.6 秒,则 t = 0.6 / 2 = 0.3。代入公式:p(0.3) = 0.3³ × (10 - 15×0.3 + 6×0.3²) = 0.027 × (10 - 4.5 + 0.54) = 0.027 × 6.04 ≈ 0.163。即动画进度从 0 缓动到约 16.3%,比线性 30% 更慢,符合 ease-in-out 效果。
不需要手写代码。页面上有可视化编辑区,直接拖动关键帧位置、调整缓动曲线(贝塞尔手柄)就能生成动画。右侧预览区实时显示效果,满意后复制下方自动生成的 CSS 代码即可。建议先点「预设」里的「弹跳」「淡入」等模板感受一下操作逻辑。
贝塞尔曲线横轴是时间比例(0→1),纵轴是进度比例(0→1)。如果手柄拉出右侧范围(比如 P1.x > 1 或 P3.x < 0),动画会出现「回弹」或「超出」效果,这是正常的缓动特性。如果觉得奇怪,先重置为 ease-in-out(0.42,0,0.58,1),再微调手柄位置,每次只动一个手柄。
本工具输出的是标准 CSS @keyframes + animation 属性,现代 Chrome/Firefox/Safari 都直接支持,无需 -webkit- 前缀。如果项目要兼容 iOS 12 以下或某些国产浏览器内核,建议用 Autoprefixer 工具补一下 -webkit-animation 和 -webkit-keyframes。复制代码后直接粘贴到 <style> 或 CSS 文件里就能用。
检查两个地方:① animation-duration 是否被后面更具体的声明覆盖(比如简写 animation: xxx 2s 里写了 2s,但后面又单独写 animation-duration: 4s);② 父元素或容器是否有 transition 或 animation 影响子元素。浏览器 DevTools 的 Elements → Styles 面板里勾选「:hov」→ 动画状态,能看到实际生效的 duration 值。
可以。点击时间轴下方「+ 添加关键帧」按钮,会在当前时间点插入一个关键帧(默认复制前一帧的属性),然后可以单独修改它的位置(百分比)和缓动函数。最多支持 10 个关键帧。注意:关键帧百分比必须按从小到大顺序排列,不支持跳跃或重复百分比的写法。
工具只生成 keyframes 和 animation 属性,不改变元素的初始布局。如果动画结束后元素「跳回」原位,是因为 animation-fill-mode 默认为 none,需手动设为 forwards(保持最后一帧状态)。在工具「动画属性」面板里找到 fill-mode 下拉,选 forwards。如果元素位置偏移,检查 transform-origin 是否居中。
完全浏览器端运行,所有计算(贝塞尔曲线插值、CSS 生成、预览渲染)都在本地完成,不发送任何数据到服务器。断网后刷新页面仍然可用。没有用户账号、没有数据收集,生成的代码只存在于当前页面内存中,关闭页面后自动清除。
卡顿通常是因为动画最后一帧和第一帧不连续。检查首尾关键帧(0% 和 100%)的属性值是否一致。如果动画是位移,0% 和 100% 的 transform 值应相同;如果是透明度,opacity 值应一致。工具预览区下方有个「循环预览」开关,打开后会自动检测首尾帧差异并给出提示。
手写 keyframes 需要记忆缓动函数 cubic-bezier 四个数值,且无法直观看到曲线形状。本工具提供可视化贝塞尔编辑器,拖动手柄时右侧预览同步更新,能快速试出想要的「先快后慢」「弹性回弹」等效果。另外自动补全关键帧百分比排序、校验语法错误,避免手写时漏分号或写错格式。
隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。