DEV Community

Chiun Hau You
Chiun Hau You

Posted on

[Pixi.js] Simple fade-in and fade-out effects for Sprites

In my recent Pixi.js project, I developed a custom Sprite class that supports simple fade-in and fade-out effects using the shared ticker. This is helpful when you want your Sprites to enter or exit the scene more smoothly.

Here is how I implemented it:

1. Extend the original PIXI.Sprite

First, let's create a custom Sprite class that contains two new methods:fadeIn and fadeOut.

import { Sprite } from 'pixi.js';

class CustomSprite extends Sprite {
  fadeIn() {
    ...
  }

  fadeOut() {
    ...
  }
}

export default CustomSprite
Enter fullscreen mode Exit fullscreen mode

2. Transitoning alpha value using shared Ticker

Smooth transition (and all kinds of animation) is often done by repeatedly increase or decrease some values in fast enough frequency (e.g. 24 frames per seconds or FPS).

Of course, you can achieve this by setInterval. But there's a more native way to do this in Pixi.js. That is, the PIXI.Ticker.

fadeIn() {
  this.alpha = 0;

  const ticker = PIXI.Ticker.shared;

  // declare a ticker listener
  const onTick = () => {
    // updates the alpha value little by little
    this.alpha += 0.01;

    // remove this listener once alpha reaches 1
    if (this.alpha > 1) {
      ticker.remove(onTick);
    }
  }

  // register the ticker listener
  ticker.add(onTick)
}
Enter fullscreen mode Exit fullscreen mode

As you see, if fadeIn is called, the Sprite will increase its alpha by 0.01 in every tick untill alpha is greater than 1. But this is not good enough as we can't specify the transition duration.

3. Understand how ticker works

Before continuing improving our code, we first need to know how often does the ticker ticks, so that we can calculate how much to tweak the value in each tick. Right?

For example, if the ticker runs 10 times per second evenly and you wish the transion duration to be 2 seconds, then you should increase the alpha value by 0.05 in each tick.

However, there's no guarantee that Pixi Ticker would tick exactly at the same speed or in a specific frequency (even if you have set PIXI.settings.TARGET_FPMS somewhere). Some ticks just take longer than another when the browser is doing heavier work during these periods.

Hopefully, a ticker's listener is passed with a deltaTime paramater telling you how much time has passed since the last tick. This is how deltaTime is calculated before passing to a ticker listener:

// https://github.com/pixijs/pixijs/blob/dev/packages/ticker/src/Ticker.ts#L411

const deltaTime = deltaMS * PIXI.settings.TARGET_FPMS;
Enter fullscreen mode Exit fullscreen mode

Therefor, deltaTime roughly means "how many frames have passed" since last tick. This is useful if you prefer to think of timeline in the sense of "frames".

In my case, I like to think in milliseconds rather than frames, so I would revert the conversion like this and calculate the value.

const onTick = (deltaTime) => {
  // how many milliseconds have passed since last tick
  const deltaMS = deltaTime / PIXI.settings.TARGET_FPMS;
  ...
}
Enter fullscreen mode Exit fullscreen mode

4. Specify a duration and update alpha proportionally

Now that we have gathered the important information about our ticker, we can continue finish our code.

// add a duration (MS) paramater
fadeIn(duration) {
  this.alpha = 0;

  const ticker = PIXI.Ticker.shared;

  const onTick = (deltaTime) => {
    const deltaMS = deltaTime / PIXI.settings.TARGET_FPMS;

    // increase the alpha proportionally
    this.alpha += deltaMS / duration;

    if (this.alpha > 1) {
      ticker.remove(onTick);
    }
  }

  ticker.add(onTick)
}
Enter fullscreen mode Exit fullscreen mode

As for fadeOut, everything stays the same except for the direction you change the alpha value.

5. Put it into use

Now you can create sprites with the customized Sprite class to enjoy fade-in and fade-out effects easily.

const bunny = new MySprite(bunnyTexture);

bunny.alpha = 0;
app.stage.addChild(bunny);

...

// fade in to the stage with a 3-second transition duration
bunny.fadeIn(3000);
Enter fullscreen mode Exit fullscreen mode

Check the example code here.

Top comments (0)