I have been running around in circles
I use the Web Animation API transform:translate()
to make my player run around the bases.
runto("first").then(() => runto("second"));
does the correct animation,
but then deletes the first/previous translate
to first base,
thus my player ends up in the wrong location
I have tried every combination of
- https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/composite
- https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/iterationComposite
Is it at all possible to preserve all the translates on one element?
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>
You could call
Animation#commitStyles()
after the animation completes, so that its state is "written" to your player.You now need to come back to the default
composite: "replace"
option, and you also need to modify your initial player settings so that it's positioned using CSStranslate()
instead of using itscx
andcy
values (or you could also modify your calculations so they return relative positions instead).