javascript - 在 Web 动画 API 中堆叠/添加/复合/累积多个转换=翻译动画

标签 javascript svg css-animations svg-animate web-animations-api

我一直在原地打转

我使用 Web Animation API transform:translate() 让我的玩家在基地周围奔跑。

runto("first").then(() => runto("second")); 执行正确动画,
但随后删除第一个/上一个翻译第一个基础
因此我的玩家最终出现在错误的位置

我已经尝试了每种组合

是否可以将所有翻译保留在一个元素上?

JSFiddle Playground :https://jsfiddle.net/WebComponents/8df2qsop/


  let field = document.getElementById("FIELD");
  let player = field.getElementById("player");
  function getCenter(el , { left, top, width, height } = el.getBoundingClientRect()) {
    let point = Object.assign(field.createSVGPoint(),{  x : left + width / 2, y : top + height / 2 }).matrixTransform(field.getScreenCTM().inverse());
    return { cx:~~point.x, cy:~~point.y };
  }
  function runto(destination) {
    let {cx:playerX,cy:playerY} = getCenter(player);
    let {cx:baseX  ,cy:baseY  } = getCenter(field.getElementById(destination));
    let translateX = baseX - playerX;  
    let translateY = baseY- playerY;
    let track = `<line x1="${playerX}" y1="${playerY}" x2="${baseX}" y2="${baseY}" stroke-width="10" stroke="black"/>`;
    field.insertAdjacentHTML("beforeend",track);
    return player.animate([{ 
          //transform: `translate(${0}px,${0}px)` 
          }, { transform: `translate(${translateX}px,${translateY}px)` }], 
        { duration:500, fill:"forwards", composite:"add" }
    ).finished; // return Promise
  }
  runto("first").then(() => runto("second"));
<style>
  #FIELD { background: lightgreen; width: 150px; margin: 20px }
</style>
<svg id=FIELD viewBox="0 0 250 250" transform="rotate(45)">
  <g fill="brown">
    <path id="home"   d="M 150 150 h 80 v 80 h -80 v -80z" fill="green"/>
    <path id="first"  d="M 150 20  h 80 v 80 h -80 v -80z"/>
    <path id="second" d="M  20 20  h 80 v 80 h -80 v -80z"/>
    <path id="third"  d="M 20 150  h 80 v 80 h -80 v -80z"/>
  </g>
  <circle id="player" cx="190" cy="190" r="30" fill="gold"/>
</svg>

最佳答案

您可以调用Animation#commitStyles()动画完成后,其状态将“写入”您的播放器。
您现在需要返回到默认的 composite: "replace" 选项,并且还需要修改初始播放器设置,以便使用 CSS translate() 进行定位使用其 cxcy 值(或者您也可以修改您的计算,以便它们返回相对位置)。

let field = document.getElementById("FIELD");
let player = field.getElementById("player");

function getCenter(el, { left, top, width, height } = el.getBoundingClientRect()) {
  let point = Object.assign(field.createSVGPoint(), {
    x: left + width / 2,
    y: top + height / 2
  }).matrixTransform(field.getScreenCTM().inverse());
  return {
    cx: ~~point.x,
    cy: ~~point.y
  };
}

async function runto(destination) {
  let { cx: playerX, cy: playerY } = getCenter(player);
  let { cx: baseX, cy: baseY } = getCenter(field.getElementById(destination));
  let translateX = baseX - playerX;
  let translateY = baseY - playerY;
  let track = `<line x1="${playerX}" y1="${playerY}" x2="${baseX}" y2="${baseY}" stroke-width="10" stroke="black"/>`;
  field.insertAdjacentHTML("beforeend", track);
  const anim = player.animate([{
    transform: `translate(${baseX}px,${baseY}px)`
  }], {
    duration: 500,
    fill: "forwards"
  });
  await anim.finished;
  anim.commitStyles(); // write the current state to the animated element
  anim.cancel(); // no need to keep it around anymore
}
runto("first").then(() => runto("second"));
<style>
  #FIELD {
    background: lightgreen;
    width: 150px;
    margin: 20px
  }
</style>
<svg id=FIELD viewBox="0 0 250 250" transform="rotate(45)">
  <g fill="brown">
    <path id="home"   d="M 150 150 h 80 v 80 h -80 v -80z" fill="green"/>
    <path id="first"  d="M 150 20  h 80 v 80 h -80 v -80z"/>
    <path id="second" d="M  20 20  h 80 v 80 h -80 v -80z"/>
    <path id="third"  d="M 20 150  h 80 v 80 h -80 v -80z"/>
  </g>
  <circle id="player" cx="0" cy="0" r="30" style="transform:translate(190px, 190px)" fill="gold"/>
</svg>

关于javascript - 在 Web 动画 API 中堆叠/添加/复合/累积多个转换=翻译动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74769431/

相关文章:

html - 使用 animate.css 创建效果预览

CSS - 有没有更好的方法来创建滚动的重复文本,这些文本在框的边缘出现和消失?

javascript - 将跨度放在选定的文本上

javascript - 为什么我需要 JavaScript 原型(prototype)来扩展对象?

javascript - 重叠 Paper.JS (HTML5) Canvas 和 VivaGraphJS(SVG) 图 : Capturing Events

javascript - 如何更改 SVG 文本的值?

javascript - 在 Dojo 中使用 OnClick 函数

javascript - 将从数据库检索的记录显示到对话框中

html - SVG 动画在智能手机上不流畅

html - 为什么我的 CSS 动画没有播放?