What happens
An animation a composition's script creates with el.animate() before the runtime loads lands up to a frame off after a seek, differently on each page load. A 4 s linear 100 px slide seeked to 2 s reads 50 to 51.25 px instead of 50.
The WAAPI adapter records a baseline for each animation the first time it sees it, including the animation's own currentTime at that moment (ensureBaseline in packages/core/src/runtime/adapters/waapi.ts). An animation created before the runtime has already been running on the wall clock for however long loading took, so every later seek is offset by that amount. Animations created after the runtime loads go through the adapter's Element.prototype.animate hook and are anchored where they are created.
Repro
Headless Chrome, the runtime built from main, window.__player.seek(2), then read the computed transform. Load the page several times.
<div data-composition-id="main" data-root="true" data-start="0" data-duration="10" data-width="640" data-height="360">
<div id="el" class="clip" data-start="0" data-duration="10">el</div>
</div>
<script>
document.getElementById("el").animate(
[{ transform: "translateX(0)" }, { transform: "translateX(100px)" }],
{ duration: 4000, easing: "linear", fill: "both" },
);
</script>
<!-- then the runtime script -->
Expected: translateX(50px) on every load.
Observed: 50 to 51.25 px, varying by load.
Notes
What happens
An animation a composition's script creates with
el.animate()before the runtime loads lands up to a frame off after a seek, differently on each page load. A 4 s linear 100 px slide seeked to 2 s reads 50 to 51.25 px instead of 50.The WAAPI adapter records a baseline for each animation the first time it sees it, including the animation's own
currentTimeat that moment (ensureBaselineinpackages/core/src/runtime/adapters/waapi.ts). An animation created before the runtime has already been running on the wall clock for however long loading took, so every later seek is offset by that amount. Animations created after the runtime loads go through the adapter'sElement.prototype.animatehook and are anchored where they are created.Repro
Headless Chrome, the runtime built from main,
window.__player.seek(2), then read the computed transform. Load the page several times.Expected:
translateX(50px)on every load.Observed: 50 to 51.25 px, varying by load.
Notes