Home > Blockchain >  Responsive canvas vuejs
Responsive canvas vuejs

Time:10-31

I'm trying to make my canvas fit its container, in a vue component. I fire resizeCanvas() in mounted, but the container height and width are 0. How can I have a canvas that fits its container, so that I can change the container size using css and it will update the canvas ? (Sorry for my english, i'm not fluent)

<template lang="html">
  <div class="container" ref="container">
    <canvas ref="canvas" :width="width" :height="height"></canvas>
  </div>
</template>

<script>

export default {
  name: "monster",
  data ()
  {
    return {
      width: 512,
      height: 512
    }
  }
  methods: {
    resizeCanvas(){
      console.log(this.$refs.container.offsetWidth); // logs 0
      this.width = this.$refs.container.offsetWidth
      this.height = this.$refs.container.offsetWidth
    }
  },
  mounted ()
  {
    console.log(this.$refs.container.offsetWidth) // logs 0
    window.addEventListener("resize", this.resizeCanvas);
    this.resizeCanvas()  
  },
  unmounted() {
    window.removeEventListener("resize", this.resizeCanvas);
  },
}
</script>

<style lang="css" scoped>
.container {
  width: 100%; height: 100%
}
</style>

CodePudding user response:

The mounted lifecycle hook in VueJS does not guarantee that the DOM is ready: you will need to wait for this.$nextTick() and then check the dimensions of your container element.

You can do it by moving the logic into the callback of nextTick, i.e.:

mounted () {
    this.$nextTick(() => {
        console.log(this.$refs.container.offsetWidth);
        window.addEventListener("resize", this.resizeCanvas);
        this.resizeCanvas();
    });
},

If you're familiar with the async/await way of doing things, then you can also do this:

async mounted () {
    await this.$nextTick();

    console.log(this.$refs.container.offsetWidth);
    window.addEventListener("resize", this.resizeCanvas);
    this.resizeCanvas();
},

Another possibility is to delegate this "wait for DOM to be ready" responsibility to the resizeCanvas function, so you have full abstraction and separation of concerns:

methods: {
    async resizeCanvas(){
      await this.$nextTick();
      
      this.width = this.$refs.container.offsetWidth
      this.height = this.$refs.container.offsetWidth
    }
},
mounted () {
    window.addEventListener("resize", this.resizeCanvas);
    this.resizeCanvas();
},
  • Related