🦸

PixiJS と GSAP を組み合わせる際の手順とサンプルコード

2024/04/11に公開

GSAP には PixiJS 用のプラグイン が用意されており、DOM 要素に対する操作と同じ要領で、PixiJS の要素を操作できます。
本記事は PixiJS と GSAP を組み合わせる際の手順とサンプルコードをまとめています。

リポジトリとサンプルページ

> リポジトリ
> サンプルページ

開発環境と npm ライブラリ

開発環境

ツール バージョン
Node.js 20.x.x
npm 10.x.x

npm ライブラリ

npm ライブラリ バージョン
typescript ^5.2.2
vite ^5.2.0
gsap ^3.12.5
pixi.js ^8.1.0(※)

※: うまく動作しない場合は PixiJS v7 にすること。

手順

  1. npm create vite@latest を実行して vite プロジェクトを作成します。
    • vite である必要は特にありません。お気に入りのフロントエンドプロジェクトでも OK です。
  2. npm i pixijs を実行して、PixiJS をインストールします。
  3. npm i gsap を実行して、GSAP をインストールします。
  4. TypeScript ファイルの調整をします。
    • 参考:> main.ts
    • 詳しい解説は下記です。

PixiJS + GSAP のサンプルコード解説

src/main.ts
import './reset.css'
import * as PIXI from 'pixi.js'
import { gsap } from 'gsap'
import { PixiPlugin } from 'gsap/PixiPlugin'
import bunnyImage from './assets/bunny.png'

const run = async () => {
  // GSAP プラグインを扱う際は gsap.registerPlugin() を実行します。
  gsap.registerPlugin(PixiPlugin)
  // 上記に併せて、PixiPlugin.registerPIXI() も実行します。このコードがなければ、正しく動作しません。
  PixiPlugin.registerPIXI(PIXI)

  // PixiJS の初期化を実行します。v7 から v8 にバージョンアップするにあたり、初期化方法が変更されています。
  // app.init() 関数は非同期関数なので、async・await を忘れずに。
  // v7 から v8 への更新点の詳細は https://pixijs.com/8.x/guides/migrations/v8#async-initialisation をご確認ください。
  const app = new PIXI.Application()
  await app.init({ background: '#1099bb', resizeTo: window })
  document.body.appendChild(app.canvas)

  // PixiJS のいつもの bunny ちゃんを読み込んで、ステージに表示します。
  const texture = await PIXI.Assets.load(bunnyImage)
  const bunny = new PIXI.Sprite(texture)
  bunny.anchor.set(0.5)
  bunny.position.set(app.screen.width / 2, app.screen.height / 2)
  app.stage.addChild(bunny)

  // アニメーション制御用のボタンを作成して、ステージに表示します。
  const btnContainer = new PIXI.Container()
  btnContainer.interactive = true
  const btnGraphics = new PIXI.Graphics()
  const btnText = new PIXI.Text({
    text: 'CLICK!',
    style: {
      fill: 0xffffff,
      fontFamily: 'sans-serif',
      fontSize: '32px',
      fontWeight: '900'
    }
  })
  btnGraphics.rect(0, 0, 200, 60).fill('#02706a')
  btnText.anchor.set(0.5)
  btnText.position.set(100, 30)
  btnContainer.addChild(btnGraphics, btnText)
  btnContainer.position.set(
    app.screen.width / 2 - 100,
    app.screen.height / 2 + 40
  )
  app.stage.addChild(btnContainer)

  // アニメーション中かのフラグ
  let isAnimation = false
  // 以降はボタン押下時の処理です
  btnContainer.addEventListener('pointerdown', () => {
    if (isAnimation) return
    isAnimation = true
    btnContainer.alpha = 0.5

    // GSAP の Timeline を作成します。
    const timeline = gsap.timeline({ defaults: { duration: 2 } })
    // bunny に対して、いくつかのアニメーションを指定しています。
    // timeline.to(PixiJS のオブジェクト, { pixi: { 項目名: 項目名の変化後の値 } }) でアニメーションを設定できます。
    // timeline.eventCallback() でアニメーション完了後にコールバック関数を実行しています。 
    timeline
      .to(bunny, { pixi: { colorize: 'red', colorizeAmount: 1 } })
      .to(bunny, { pixi: { hue: 180 } })
      .to(bunny, { pixi: { scale: 1.75 } })
      .to(bunny, { pixi: { saturation: 0 } })
      .to(bunny, { pixi: { brightness: 2 } })
      .to(bunny, { pixi: { contrast: 1.5 } })
      .to(bunny, { pixi: { scale: 1 } })
      .eventCallback('onComplete', () => {
        isAnimation = false
        btnContainer.alpha = 1
      })
  })
}

run()

まとめ

PixiJS と GSAP を組み合わせる際のサンプルコードでした。
思った以上にすぐに連携できますし、PixiJS の要素の操作もカンタンでした。

機会がありましたら、PixiJS + GSAP + Spine で何か作ってみたいと思います!

Discussion