Vue(Vite)でPixiが表示できないエラー

updated 2021-6-1

問題

いつもVue(Vite)先生にお世話になっているので、相も変わらず使わせていただいていたのですが、 サクサクっとできそうな表示でつまづいてしまいました。

環境

{
  ...
  "dependencies": {
    "pixi.js": "^6.0.4",
    "vue": "^3.0.5"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.2.2",
    "@vue/compiler-sfc": "^3.0.5",
    "vite": "^2.3.4"
  }
}

コード

App.vue

<template>
  <Pixi />
</template>

<script setup>
import Pixi from './components/Pixi.vue'
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  overflow: hidden;
  width: 100%;
  height: 100%;
}
html, body {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
}
</style>

components/Pixi.vue

<template>
  <div id="pixi" ref="pixi"></div>
</template>

<script>
import * as PIXI from "pixi.js";

export default {
  data: () => ({
    app: null,
    width: 640,
    height: 960,
  }),
  methods: {
    init() {
      this.app = new PIXI.Application({
        width: this.width,
        height: this.height,
        backgroundColor: 0x1099bb,
        resolution: window.devicePixelRatio || 1,
        view: this.$refs.pixi,
      });
    },
  },
  mounted() {
    this.init();
  },
};
</script>

<style>
#pixi {
  height: 100%;
  width: 100%;
}
</style>

エラー

ContextSystem.ts:149 Uncaught TypeError: canvas2.getContext is not a function
    at ContextSystem2.createContext (ContextSystem.ts:149)
    at ContextSystem2.initFromOptions (ContextSystem.ts:129)
    at new Renderer2 (Renderer.ts:300)
    at Function.Renderer2.create (Renderer.ts:106)
    at autoDetectRenderer (autoDetectRenderer.ts:42)
    at new Application2 (Application.ts:107)
    at Proxy.init (Pixi.vue:16)
    at Proxy.mounted (Pixi.vue:26)
    at callWithErrorHandling (runtime-core.esm-bundler.js:154)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:163)

試行錯誤

ちゃんとドキュメント読むかな...って始めてみた
https://github.com/kittykatattack/learningPixi#introduction

Hello World

<script>
import * as PIXI from "pixi.js";

export default {
  methods: {
    test() {
        let type = "WebGL"
        if(!PIXI.utils.isWebGLSupported()){
        type = "canvas"
        }

        PIXI.utils.sayHello(type)
    }
  },
  mounted() {
    this.test();
  },
};
</script>

Hello Worldはできていた

View

App.vue

<template>
  <Pixi />
</template>

<script setup>
import Pixi from './components/Pixi.vue'
</script>

<style>
#app {
  ...
  width: 100%;
  /* height: 100%; */
}
html, body {
  ...
}
</style>

components/Pixi.vue

<script>
import * as PIXI from "pixi.js";

export default {
  methods: {
    test() {
        let app = new PIXI.Application({
            width: 256,
            height: 256,
        });

        document.body.appendChild(app.view);
    }
  },
  mounted() {
    this.test();
  },
};
</script>

アプリの割り当ても問題なく完了...

キャンバスサイズ

<script>
...
export default {
  methods: {
    test() {
            let app = new PIXI.Application({ 
                width: 256,         // default: 800
                height: 256,        // default: 600
                antialias: true,    // default: false
                transparent: false, // default: false
                resolution: 1,      // default: 1
                backgroundColor: 0xcccccc, // add background
                view: document.body, // document.bodyに表示
            });

            document.body.appendChild(app.view);
    }
  }
}
...
</script>

表示されるしグレーになった...

キャンバスの位置変更

<script>
...
export default {
  data: () => ({
    app: null,
    width: 640,
    height: 960,
  }),
  methods: {
    test() {
        let app = new PIXI.Application({ 
            width: this.width,         // default: 800
            height: this.height,        // default: 600
            antialias: true,    // default: false
            transparent: false, // default: false
            resolution: 1,       // default: 1
            backgroundColor: 0xcccccc,
        });

        this.$refs.pixi.appendChild(app.view);
    }
  }
}
...
</script>

表示できる

defaultでviewを与える

<template>
  <div id="pixi" ref="pixi"></div>
</template>

<script>
import * as PIXI from "pixi.js";

export default {
  data: () => ({
    app: null,
    width: 640,
    height: 960,
  }),
  methods: {
    test() {
        let app = new PIXI.Application({ 
            width: this.width,
            height: this.height,
            antialias: true,
            transparent: false,
            resolution: 1,
            backgroundColor: 0xcccccc,
            view: this.$refs.pixi,
        });
    }
  },
  mounted() {
    this.test();
  },
};
</script>

<style>
#pixi {
  height: 100%;
  width: 100%;
}
</style>

ここでエラー吐いて落ちる

解決方法

<template>
  <div id="pixi">
      <canvas ref="pixi" />  <!-- ここ変更 -->
  </div>
</template>

<script>
import * as PIXI from "pixi.js";

export default {
  data: () => ({
    app: null,
    width: 640,
    height: 960,
  }),
  methods: {
    init() {
        let app = new PIXI.Application({ 
            width: this.width,         // default: 800
            height: this.height,        // default: 600
            antialias: true,    // default: false
            transparent: false, // default: false
            resolution: 1,       // default: 1
            backgroundColor: 0xcccccc,
            view: this.$refs.pixi,
        });

        this.$refs.pixi.appendChild(app.view);
    }
  },
  mounted() {
    this.init();
  },
};
</script>

<style>
#pixi {
  height: 100%;
  width: 100%;
}
</style>

canvasを自動で作成してくれるわけではないので、自分でcanvasを用意して与えればできた