Skip to content
Advertisement

Error in camera App / Type error: null on ‘getContext’

I have a b-modal with a camara app.

First I had my <video> and my canvas seperate – but now I want to have them overlapping each other. So first I want to show my video with my button make photo – if I press this my canvas with the taken photo and the other two buttons delete upload should be shown.

But I always get following error (I made a comment in my code where the error is):

[Vue warn]: Error in v-on handler: “TypeError: Cannot read properties of null (reading ‘getContext’)”

How can I handle this? Thanks!

<template>
  <div :id="IDParent+'camera'">
    <div class="text-center" info>
      <div center :close="false">
        <p class="heading">Make photo</p>
      </div>
      <div>
        <video v-if="hide" class="mb-4" ref="video" id="video" width="100%" height="100%" autoplay />
        <canvas v-if="!hide" class="mb-4" id="responsive-canvas"></canvas>
        <div class="row mb-5">
          <div class="col-md-12">
            <b-button v-if="hide" variant="block p-3 colorSuccess" @click="takePicture()"><b-icon icon="camera-fill"></b-icon> Make Photo</b-button>
          </div>
          <div class="col-md-4">
            <b-button v-if="!hide" variant="block p-3 colorDanger mb-2" @click="deletePicture()"><b-icon icon="exclamation-circle-fill"></b-icon> Delete </b-button>
          </div>
          <div class="col-md-8">
            <b-button v-if="!hide" variant="block p-3 colorSuccess" @click="uploadPicture()"><b-icon icon="cloud-upload"></b-icon> upload photo</b-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>

export default {
  data() {
    return {
      video: {},
      canvas: {},
      captures: [],
      push: false,
      hide: true,
    }
  },

  props: [
    "IDParent",
    ],

  mounted() {
    this.video = this.$refs.video;
    if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
             this.video.srcObject = stream;
                this.video.play();
                this.video.onplay = function () {
                };
                this.video.play();
        });
    }
    },

  methods: {

    closeModal() {
      
    },

    uploadPicture() {

    },

    takePicture() {
      if(this.hide == true) {
      const picture = document.querySelector("canvas"); //ERROR IN THIS LINE! 
      const ctx = picture.getContext("2d");
      ctx.imageSmoothingEnabled = true;
      ctx.imageSmoothingQuality = "high";
      ctx.drawImage(document.querySelector("video"), 0, 0, picture.width, picture.height);
      }
      this.hide = false;
    },

    showCanvas() {
        var canvas = document.getElementById('responsive-canvas');
        var heightRatio = 0.75;
        canvas.height = canvas.width * heightRatio;
    },

    deletePicture() {
      const inputPicture = document.querySelector("canvas");
      const context = inputPicture.getContext("2d");
      context.clearRect(0, 0, inputPicture.width, inputPicture.height);

      this.hide = true;
    },

    capture() {
        this.canvas = this.$refs.canvas;
        this.canvas.getContext("2d").drawImage(this.video, 0, 0, 640, 480);
        this.captures.push();
    },
  }
}

</script>

Advertisement

Answer

If you carefully observe the below function,

 takePicture() {
      if(this.hide == true) {
      const picture = document.querySelector("canvas"); //ERROR IN THIS LINE! 
      const ctx = picture.getContext("2d");
      ctx.imageSmoothingEnabled = true;
      ctx.imageSmoothingQuality = "high";
      ctx.drawImage(document.querySelector("video"), 0, 0, picture.width, picture.height);
      }
      this.hide = false;
    },

the above gets triggered on clicking the below button

<b-button v-if="hide" variant="block p-3 colorSuccess" @click="takePicture()"><b-icon icon="camera-fill"></b-icon> Make Photo</b-button>

Note the condition v-if=”hide”, at this instant you canvas is hidden from the Dom because of the below condition that you have used

<canvas v-if="!hide" class="mb-4" id="responsive-canvas"></canvas>

Thats the reason why when you try to query it, its showing error.

Modify your condition so that its available on DOM and then try to access it

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement