popmotion icon indicating copy to clipboard operation
popmotion copied to clipboard

Popmotion: Animation duration stretched when using pixi.js Ticker as animation driver

Open farhat-h opened this issue 3 years ago • 2 comments

Describe the bug

Animation duration is stretched when using pixijs Ticker (update loop) as driver.

How to reproduce

Create a driver that adds the update method to the ticker on start and removes it to stop. The ticker will call the update method with delta time. The ticker also uses Performance.now() timer

const tickerDriver: Driver = (update) => {
  return {
    start: () => app.ticker.add(update),
    stop: () => app.ticker.remove(update)
  };
};

// usage
animate({
    ...options,
    driver: tickerDriver
  });

Expected behaviour

Duration is not stretched.

Link to CodePen example (or similar)

CodeSandbox: https://codesandbox.io/s/ecstatic-fog-6j7xg?file=/src/index.ts:485-630

Device information

In which environment are you reproducing the bug?

  • Device: [Desktop]
  • OS: [Windows 10]
  • Browser [Firefox, Chrome and Opera] (same problem on all of them)

Additional context

Permalink to Ticker update method

At first I thought it was a timer resolution issue because multiplying dt by 10 and passing it to update made it the issue go away (kinda)


const tweakedTickerDriver: Driver = (update) => {
  const updateAnim = (dt :number) => {
    update(dt * 10)
  }
  return {
    start: () => app.ticker.add(updateAnim),
    stop: () => app.ticker.remove(updateAnim)
  };
};

but both use performance.now i believe

farhat-h avatar Dec 12 '21 13:12 farhat-h

I now that this is an old issue and it shouldn't be one to you at this time. But i took a look at your sandbox and played with it. I will leave here a comment for anyone who may stumble upon it later since this is still open.

I am not sure what you meant by "stretched ", but your animation had a little bug which made the animation be inconsistent because the update callback is calculating the circle.x value using the whole window width.

onUpdate: (current) => {
    circle.x = current % window.innerWidth;
  }

This should be changed to the width of the pixi element instead.

onUpdate: (current) => {
    circle.x = current % app.renderer.view.clientWidth;
  }

By the way, i didn't know that nice trick with the modulo to achieve that type of animation. It is so logical for this type of situation, once one see it. This really shows how much animation i have made (or not) along the years 😎 Thanks for the tip.

audiBookning avatar Jul 27 '22 02:07 audiBookning

I came across this issue and took a look.

Problem isn't related to popmotion. popmotion's update expects delta time in ms, but pixi's ticker passes to its update something different (meaningless deltaTime measured in frames related to 60fps). Proper delta time hidden in ticker.elapsedMS. See.

So solution is:

const tickerDriver: Driver = (update) => {
  const tweakedUpdate = () => update(app.ticker.deltaMS)

  return {
    start: () => app.ticker.add(tweakedUpdate),
    stop: () => app.ticker.remove(tweakedUpdate)
  }
}

Don't know why this is still open, pretty sure author found solution a while ago.

zumm avatar May 19 '23 12:05 zumm