title: canvas adjust image to video tag proportions
body: <p>I developed a project that when registering, you have to take a picture. Customers asked for the camera or video tag to be at 100% screen height. However, above this camera/video goes a filter, so the video tag receives the width of this image/filter and the height of the screen every time. The video tag has an object-fit:cover to get 100%. The challenge now is to adjust this on the canvas, to make the image appear with the same size. The problem is the width because the width is the same as the filter, there is no way to actually know the width of the video.</p>
  <p>Video component</p>
  <pre><code>&lt;template&gt;
    &lt;div class=&quot;takePhoto__camera&quot;&gt;
      &lt;video ref=&quot;video&quot; fullscreen=&quot;false&quot; playsinline muted&gt;&lt;/video&gt;
      &lt;img class=&quot;takePhoto__camera__filter&quot; src=&quot;../../assets/images/filtro.png&quot; ref=&quot;filter&quot; alt=&quot;Filtro&quot;&gt;
      &lt;button class=&quot;takePhoto__camera__btn&quot; @click.prevent=&quot;photoTaken&quot;&gt;&lt;/button&gt;
    &lt;/div&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
  import { mapMutations } from &quot;vuex&quot;
  
  export default {
    name: &quot;ComponentCameraVideo&quot;,
  
    data(){
      return{
        video: null,
        localStream: null,
      }
    },
  
    mounted(){
      this.video = this.$refs.video;
      this.init();
    },
  
    methods: {
      ...mapMutations([&quot;SET_CAMERA&quot;]),
  
      init(){
        const filter = document.querySelector(&quot;.takePhoto__camera__filter&quot;);
  
        // Seta a classe ao body
        document.body.classList.add(&quot;takingPicture&quot;);
  
        filter.onload = () =&gt; {
          // Pedir permissão para acessar a câmera
          if('mediaDevices' in navigator &amp;&amp; 'getUserMedia' in navigator.mediaDevices){
            navigator.mediaDevices.getUserMedia({video: true}).then((stream) =&gt; {
              this.video.srcObject = stream;
              this.localStream = stream;
              this.video.play();
              this.setWidthVideo();
            }).catch((error) =&gt; {
              console.log(error)
              alert(error);
            })
          }
          else{
            alert(&quot;Não foi possível acessar a câmera!&quot;);
          }
        }
        
      },
  
      photoTaken(){
        // Remover a classe do body
        document.body.classList.remove(&quot;takingPicture&quot;);
  
        // Setar a câmera na variável vuex
        this.SET_CAMERA(
          {
            &quot;video&quot; : {
              element: this.video,
              width: this.video.offsetWidth, 
              height: this.video.offsetHeight
            },
            &quot;filter&quot; : {
              element: this.$refs.filter,
              width: this.$refs.filter.offsetWidth, 
              height: this.$refs.filter.offsetHeight
            },
            &quot;stream&quot; : this.localStream,
          }
        );
  
        // Emitir o evento
        this.$emit(&quot;photoTaken&quot;);
  
        // Parar a execução da câmera
        // this.localStream.getTracks()[0].stop();
      },
  
      setWidthVideo(){
        setTimeout(() =&gt; {
          // Setar largura para o vídeo de acordo com o filtro
          const video = document.querySelector(&quot;.takePhoto__camera video&quot;);
          const filter = document.querySelector(&quot;.takePhoto__camera__filter&quot;);
        
          video.style.width = filter.offsetWidth + &quot;px&quot;;
          video.style.height = innerHeight + &quot;px&quot;;
        }, 500)
      }
    },
  }
  &lt;/script&gt;
  </code></pre>
  <p>Canvas component</p>
  <pre><code>&lt;template&gt;
    &lt;div class=&quot;takePhoto__showPhoto&quot;&gt;
      &lt;canvas ref=&quot;canvas&quot;&gt;&lt;/canvas&gt;
      &lt;img :src=&quot;src&quot; alt=&quot;Sua foto&quot;&gt;
    &lt;/div&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
  import { mapState, mapMutations } from &quot;vuex&quot;
  
  export default {
    name: &quot;ComponentCameraCanvas&quot;,
  
    data() {
      return {
        canvas: null,
        src: &quot;/&quot;,
      };
    },
  
    computed: {
      ...mapState([&quot;camera&quot;])
    },
  
    mounted() {
      this.canvas = this.$refs.canvas;
      this.getPhoto()
    },
  
    methods: {
      ...mapMutations([&quot;SET_PHOTO&quot;]),
  
      getPhoto(){
        const ratio = (window.innerHeight &lt; window.innerWidth) ? 16 / 9 : 9 / 16;
        const ctx = this.canvas.getContext(&quot;2d&quot;);
  
        // Setar tamanho para o Canvas
        this.canvas.width = this.camera.filter.width;
        this.canvas.height = this.camera.filter.height;
  
        // Configs do canvas
        ctx.imageSmoothingEnabled = true;
        ctx.imageSmoothingQuality = &quot;high&quot;;
        
        // Filtro
        let filter = new Image();
        filter.src = this.camera.filter.element.src
  
        // Inserindo as imagens no canvas
        ctx.drawImage(this.camera.video.element, 0, 0);
        ctx.drawImage(filter, 0, 0, this.camera.filter.width, this.camera.filter.height);
  
        // Parar a execução da câmera
        this.camera.stream.getTracks()[0].stop()
  
        // Salvar na variável photo - vuex
        this.SET_PHOTO(this.canvas.toDataURL(&quot;image/jpeg&quot;));
  
        // Motrar na tag image
        this.src = this.canvas.toDataURL(&quot;image/jpeg&quot;);
      },
    },
  }
  &lt;/script&gt;
  
  &lt;style lang=&quot;scss&quot; scoped&gt;
  #picture {
    display: block;
    width: 100%;
    height: 100vh;
    box-sizing: border-box;
  
    canvas {
      display: block;
      width: 100%;
      height: 100%;
    }
  }
  &lt;/style&gt;
  
  </code></pre>
  <p>I'm using vue to store the values</p>
  <p><a href="https://torcida.petronas.com.br/stg" rel="nofollow noreferrer">https://torcida.petronas.com.br/stg</a></p>