登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  前端

JavaScript Animation.commitStyles 怎样将动画当前位置写入样式

来源:17golang原创

时间:2026-10-27 14:43:05 324浏览 收藏

热门推荐
漫画APP
动画内容聚合,热门资源快捷查看
立即下载

如果一个 Web Animations API 动画结束后还要保留它当前的位移、透明度或其他计算样式,可以调用 animation.commitStyles()。它会把动画当前的计算值写入目标元素的 style 属性;调用没有参数,返回值是 undefined。实际使用时,通常先等待 animation.finished,再提交样式。

最小写法是:创建动画,等待 finished,调用 commitStyles()。如果要兼容仍要求填充模式的旧浏览器,给动画加上 fill: "forwards",提交后再调用 cancel() 清掉持续填充状态。

官方资料:https://developer.mozilla.org/en-US/docs/Web/API/Animation/commitStyles

commitStyles 写入的到底是什么

commitStyles() 操作的是动画目标元素,而不是创建一份新的 DOM 节点。它读取动画当前位置对应的计算样式,并将这些值写入目标元素的 style 属性。这样动画对象不再是唯一的样式来源,元素后续可以像普通内联样式一样继续修改。

const card = document.querySelector('.card');

if (!card) {
  // 目标元素不存在时先停止,避免对 null 创建动画。
  throw new Error('找不到动画目标');
}

const animation = card.animate(
  { transform: ['translateX(0)', 'translateX(160px)'], opacity: [1, 0.7] },
  { duration: 600, easing: 'ease-out' },
);

// 等动画完成后,把当前位置的计算值写进目标元素的 style 属性。
await animation.finished;
animation.commitStyles();

// 提交后仍可像普通内联样式一样继续修改。
card.style.opacity = '1';
Animation 当前计算值通过 commitStyles 写入目标元素 style 属性的静态关系图
图1:Animation.commitStyles() 将动画当前计算值写入目标元素 style 属性的静态关系图,不是运行截图或执行证据。

用 finished 等待动画结束再提交

标题里的“当前位置”并不只指最终关键帧。只要在动画仍运行时调用,提交的就是调用时刻的计算值;如果需求是保存最终状态,最清楚的边界是等待 animation.finished 兑现后再调用。这样调用点和“保存最终结果”的意图一致,也避免在动画尚未到达目标值时提前写入。

async function settlePanel(panel) {
  if (!panel) {
    // 调用方传入空节点时返回一个可识别的错误。
    throw new Error('panel 不能为空');
  }

  const animation = panel.animate(
    { transform: ['translateY(20px)', 'translateY(0)'] },
    { duration: 450, fill: 'none' },
  );

  try {
    // finished 在动画正常完成后兑现,随后再提交最终计算值。
    await animation.finished;
    animation.commitStyles();
  } catch (error) {
    // 动画被取消时不要把未完成的中间状态当成最终样式。
    if (animation.playState !== 'idle') {
      throw error;
    }
  }
}

await settlePanel(document.querySelector('.panel'));

这里的关键顺序是 finished 在前、commitStyles() 在后。方法本身不需要传入属性名或目标元素,因为目标元素和当前动画状态已经保存在 Animation 对象里。

fill: forwards 与 cancel() 怎么配合

在较新的浏览器中,动画结束后不设置 fill 也可以提交样式;但为了照顾仍要求填充模式的旧环境,稳妥写法是使用 fill: "forwards"。提交完成后应调用 cancel(),否则填充动画会一直优先于静态样式,影响元素之后的正常样式更新。

async function commitWithCompatibility(button) {
  if (!button) {
    // 没有目标按钮就不创建动画。
    throw new Error('button 不能为空');
  }

  const animation = button.animate(
    { transform: ['translateX(0)', 'translateX(100px)'] },
    // fill 让旧浏览器在 finished 后仍能读取最终状态。
    { duration: 500, fill: 'forwards' },
  );

  // 先等待最终状态,再把它写入 style 属性。
  await animation.finished;
  animation.commitStyles();

  // 提交完成后取消填充动画,避免它继续压过静态样式。
  animation.cancel();
}

await commitWithCompatibility(document.querySelector('.move-button'));
现代浏览器与旧浏览器兼容写法中 finished、fill、commitStyles 和 cancel 的静态关系对比图
图2:现代浏览器写法与 fill: forwards 兼容写法的静态策略对比图,不是浏览器界面截图。

如果项目只支持已经确认具备新行为的浏览器,可以省略 fill 和后续的 cancel();如果发布范围无法精确控制,保留兼容写法更容易解释,也更不容易留下一个长期填充的动画对象。

调用时机和返回值要怎么判断

这个方法的 API 形状很简单,但调用时机决定了结果:

问题结论写法
需要保存最终状态等待动画完成后提交await animation.finished; animation.commitStyles()
需要保存某个中间位置在指定时刻直接提交animation.commitStyles()
需要兼容旧环境提交前保留填充,提交后取消动画fill: "forwards" + cancel()
想读取方法结果不要期待返回节点或样式对象返回值是 undefined

commitStyles() 不会替你重新播放动画,也不会把动画对象转换成新的 CSS 规则。它只是在调用点把当前计算值落到元素的内联样式上。调用完成后可以继续更新 element.style,也可以根据业务需要重新创建下一段动画。

最后用四个问题选择写法

  • 保存的是最终状态还是中间状态?最终状态先等待 finished,中间状态按时机直接提交。
  • 目标浏览器是否包含仍要求填充模式的旧环境?不确定时使用 fill: "forwards",提交后调用 cancel()。
  • 是否误以为方法需要参数?不需要参数,目标元素和当前值来自 Animation 对象。
  • 是否把返回值当作新样式对象?不应这样做;返回值为 undefined,需要继续修改时直接操作目标元素的 style。

相关问题

commitStyles() 会把动画转成 CSS 规则吗?

不会。它把当前计算值写入目标元素的 style 属性,不会生成新的样式表规则。

为什么调用 commitStyles() 后还要 cancel()?

当动画用了 fill: "forwards" 时,填充状态会继续参与样式优先级。提交后取消动画,可以让已经落地的内联样式接管后续状态。

commitStyles() 有参数或返回值吗?

它没有参数,返回 undefined。方法通过当前 Animation 实例找到目标元素和计算样式。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>