Search code examples
javascriptvue.jsvuexvue-routerpixi.js

Dynamic PixiJS canvas goes wrong after first load in vue app


I'm building a website with Vue.js and use PixiJS to dynamically draw a canvas with data that comes from a big json file. The canvas is generated as a component and used in a view.

Now the first time when I navigate to the view with the canvas, it all looks fine. But when I start navigating between views, the drawing is all messed up, the sprites are all there but it looks all out of place and messy. When I then refresh the page, the canvas looks fine again. Here is an image:

enter image description here

I'm not sure what the problem is here, but I feel like it's a combination of things. Maybe the 100k line json file I'm working with has something to do with it (the view also feels kind of slow when I interact with it)

This is kind of how my Vue component looks like:

export default {
  name: 'Tree',
  data () {
    return {
      tree: {},
      app: new PIXI.Application()
    }
  },
  beforeMount () {
    this.tree = this.treeStateData
    PIXI.utils.clearTextureCache()
    PIXI.loader.reset()
  },
  mounted () {
    this.loadTree()
  },
  computed: {
    ...mapState([
      'treeStateData'
    ])
  },
  methods: {
    loadTree () {
      document.getElementById('tree').appendChild(this.app.view)

      // Load images
      PIXI.loader
        .add('background', require('@/assets/Background1.png'))
        .add('1', require('@/assets/PSGroupBackground1.png'))
      // lots more
        .load(this.drawTree)
    },
    drawTree () {
      const treeData = this.tree

      // Create viewport
      const viewport = new Viewport()
      this.app.stage.addChild(viewport)

      // Here i create some containers

      // Here i work with the data from the json and put stuff in the containers
    }
  }
}

The structure of my Vue project is like this:
Views

views/home.vue    
// Just a view with a link to details.vue

views/details.vue    
// A view that had <tree> component in it
<template>
  <div>
    <tree></tree>
  </div>
</template>

<script>
import Tree from '@/components/tree'

export default {
  name: 'Details',
  data () {},
  components: {
    Tree
  }
}
</script>

Components

components/tree.vue
// Here is where the tree canvas is generated

Anyone got an idea on how to make progress on this? Should i rethink how i do this?


Solution

  • Since everything is working on the first load, caching the component may help when navigating between routes. It also saves recalculating the PixiJS display each time.

    Wrap the router-view in a keep-alive component:

    <keep-alive>
       <router-view></router-view>
    </keep-alive>