Uploading an Image to an HTML Canvas Element with Vue2

I came across a situation where I needed to, essentially, take an image and slap it into a canvas element. It turned out to be pretty simple code to accomplish, but I ran into a few sticking points so I thought I would share the code.

The Template

The template is straight forward. An input to select the image, and a canvas element to put the image into.

<template>
    <div class="journey">
        <input type="file" id="imageLoader" @change="updateCanvasImage"/>
        <canvas id="imageCanvas" ref="imageCanvas"></canvas>
    </div>
</template>

There are two notable things here. First, the @change  syntax for handling the onChange  event. This will call our updateCanvasImage  method any time the image changes. Second, the ref=  property on our canvas. We’ll use this in our method to tell the image where it will be written to.

The script

The real meat of this, the script, is fairly straight forward too. The only thing that really tripped me up was in the img.onload  function, I was originally trying to call this.$refs.imageCanvas  there and was getting the beloved “undefined” error in the console.

After Googling around finding all different explanations for why this wasn’t working, I finally decided to log this  to see what was going on in there… which was when I realized this  was referencing the event, instead of the Vue instance.

Enter var self = this; . Once I set this and changed from this.$refs  to self.$refs , everything worked beautifully. Then I went ahead and cleaned up the code a little more and moved the canvas drawing itself to a separate method.

Below is the final product.

<script>
export default {

    methods: {
        updateCanvasImage(e) {

            var self = this;

            var reader, files = e.target.files;

            var reader = new FileReader();

            reader.onload = (e) => {
                var img = new Image();
                img.onload = function() {
                    self.drawCanvasImage(img)
                }
                img.src = event.target.result;
            };

            reader.readAsDataURL(files[0]);

        },

        drawCanvasImage(img) {
            var canvas = this.$refs.imageCanvas;
            canvas.width = img.width;
            canvas.height = img.height;

            var ctx = canvas.getContext('2d');
            ctx.drawImage(img,0,0);
        }
    }
}
</script>

 

Leave a Reply

Your email address will not be published. Required fields are marked *