[SOLVED] How to embed playcanvas into Vue programs instead of vice versa

As mentioned above, I am trying to embed playcanvas into the Vue program. I have retrieved some examples that integrate Vue into Playcanvas. Is there any good way to reverse it? I heard that we can consider using the source version, can anyone give me some guidance? thank.

Hi @kprimo,

I don’t have much experience with Vue.js but I know it should be similar with react and angular.

If you search the forums for react you will find some insightful posts:

Hi @kprimo
As @Leonidas linked, you can either embed an iframe and run an app through the public folder, or use the more direct approach with NPM.
It is very similar to the webpack template (https://github.com/playcanvas/playcanvas-webpack)
You can simply npm install playcanvas and then import * as pc from 'playcanvas';.

I modified the HelloWorld component from Vue to contain a Playcanvas app;

  <div class="hello">
    <h1>{{ msg }}</h1>
    <canvas id="game" style="width: 50em; height: 25em"></canvas>
import * as pc from 'playcanvas';

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  data: function() {
    return {
      app: undefined
    this.app = new pc.Application(document.getElementById('game'));
    // create box entity
    const box = new pc.Entity('cube');
    box.addComponent('model', {
        type: 'box'

    // create camera entity
    const camera = new pc.Entity('camera');
    camera.addComponent('camera', {
        clearColor: new pc.Color(0.1, 0.1, 0.1)
    camera.setPosition(0, 0, 3);

    // create directional light entity
    const light = new pc.Entity('light');
    light.setEulerAngles(45, 0, 0);

    // rotate the box according to the delta time since the last frame
    this.app.on('update', dt => box.rotate(10 * dt, 20 * dt, 30 * dt));


Hope it helps.


Thank you for sharing, @Ivolutio!

1 Like

I’m actually working on a project that uses Vue.JS right now. Ended up going with a little more unconventional way of integrating by forgoing PlayCanvas NPM package entirely. However, it only takes me a second to export a new version of the project from PlayCanvas and have it working in Vue, so I’ve found that convenient. If you stick the exported files right in the “public” folder, and use a slightly modified index.html then it should work.

If it helps, this is what my public/index.html looks like:

    <!-- Vue.JS app root -->
    <div id="app"></div>
    <!-- PlayCanvas -->
    <link rel="manifest" href="./playcanvas/manifest.json">
    <script src="./playcanvas/playcanvas-stable.min.js"></script>
    <script src="./playcanvas/settings.js"></script>
      // PlayCanvas project location settings
      var PREFIX = '/playcanvas/';
      var CONFIG_FILENAME = PREFIX + 'config.json';
    <script src="./playcanvas/start.js" defer></script>
    <script src="./playcanvas/loading.js" defer></script>

When I export the lastest project from PlayCanvas, I unzip everything into the ./public/playcanvas folder.

This method is a little less flexible though. I end up moving the <canvas> DOM element into a Vue component on load.


thank you for your sharing. I think I’ll adopt your plan.

1 Like

Hello, do you have any more examples?


Thanks for your help!
I’ve got it to work with your instructions, however I’ve tried to load a model file in json format via loadFromUrl() and I only get html response headers. I’m fairly new to vue and not sure if I configured it (or webpack) correctly.

Here is exactly what I did:

  1. npm install -g @vue/cli (newest version)
  2. vue create projectname
  3. cd projectname
  4. vue add router
  5. npm install playcanvas
  6. edit main.js:
    add lines:
    import * as pc from 'playcanvas';
    Vue.prototype.$pc = pc
  7. Vue router created two pages (Home.vue & About.vue) with routes for me, I edited About.vue and added the following code:
  <div class="about">
    <canvas id="game" style="width: 50em; height: 25em"></canvas>

export default {
  name: 'About',

  data() {
    return {
      app: undefined

  mounted() {

    this.app = new this.$pc.Application(document.getElementById('game'));

    const url = "../assets/models/s01.json";
    const environment = new this.$pc.Entity('Environment');

    // load model file
    this.app.assets.loadFromUrl(url, "model", function (err, asset) {
      environment.model.model = asset.resource;
      environment.setLocalPosition(0, 0, 0);

    // create camera entity
    const camera = new this.$pc.Entity('camera');
    camera.addComponent('camera', {
        clearColor: new this.$pc.Color(0.1, 0.1, 0.1)
    camera.setPosition(0, 0, 6);

    // create directional light entity
    const light = new this.$pc.Entity('light');
    light.setEulerAngles(45, 0, 0);





Then when I use npm run serve and check it in the browser, I get the console error:
“Error loading model: s01.json [SyntaxError: Unexpected token < in JSON at position 0]”

When checking the headers in chrome dev-tools the response headers are:
Content-Type: text/html; charset=UTF-8

Those should be application/json as far as I know, but I don’t know how to make that happen :smiley:

Any help is greatly appreciated.

Hi @patriboz
Where is your assets/models/s01.json located? If you put it in the src folder, try moving it to the public folder where your index.html is.

You were right, it was located in /src/, but after copying the assets to the public folder, I still get the same error and same html response header.

In that case, I think you should be able to see the request url for that file in the network tab of chrome. Can you share that, as well as your folder structure of your Vue project?

Sure. The request url is: http://localhost:8080/public/models/s01.json
And the folderstructure is:


In the code I used this url after copying the model to public: ../../public/models/s01.json

Remove public from the url. I think it should be relative from the public folder, as the site’s index.html is located there.
So the correct path: ./models/s01.json

1 Like

Oh yes, that did the trick. Thank you so much!

I’ve got some other errors now, but I think I can fix them myself. If not, I’ll get back to you :smiley:

EDIT: All fixed. Works like a charm now. Thank you!

1 Like

Hi, this works good. Only thing I discovered is that the MiniStats from the playcanvas-extras do not work. It seems that the “pc” directive cannot be accessed :frowning: Does anyone have an Idea? I got the error that pc is undefined inside the playcanvas-extras.js script.


Is the order of the scripts correct? (Ie is playcanvas included before extras)

It might be because ‘pc’ isnt registered on the ‘window’. So when you have created your app, try this: window.pc = pc;


Great, that was the cause @Ivolutio ! Thanks a lot - silly me :frowning:

1 Like

Hi I wonder, how you structure your Vue.js projects and how you use components.
Most components are renderless I guess. I found a project which combines Vue and Babylon.js https://github.com/Beg-in/vue-babylonjs
Would it be a good approach if it work similar like this or I guess it es enough to structure components as .js files and import them…

That is an interesting way to structure your apps, thanks for sharing.
I am personally only using JavaScript to add entities and components to my playcanvas app, but if that other kind of structure makes sense for you I don’t see why it wouldn’t work. It probably depends on what app you’re creating and why you’re using Vue in the first place.