Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
September 14, 2021 02:10 pm GMT

Create Signature Component in Vue

Hello, today we will see how to create a signature component using vuejs.

Creating your own components is very useful when you have specific needs, it also allows you to learn the logic behind the component.

Use canvas

We are going to use a canvas HTML tag, this will allow the user to draw his signature.

<template>    <canvas /></template>

Add some style :

<style scoped>canvas {    border: 1px solid black;    background-color: white;    cursor: crosshair;}</style>

Note:

  • Here we use the scoped property on the style tag which allows to keep the style inside the component.
  • I define the cursor by a crosshair (the details make the differences).

It's time to use javascript !

First of all we will get our canvas and pass it some parameters

data() {    return {        ctx :  null,    }},mounted(){    this.ctx  = this.$el.getContext('2d')    this.ctx.strokeStyle  =  'black'    this.ctx.lineWidth  =  2}

Notes:

  • strokeStyle is the color of the signature
  • lineWidth is the width of the signature

Let's add the mousedown event to our canvas which will let us know when the user clicks on our canvas.

<template>    <canvas @mousedown=onMouseDown /></template>
data(){    return {        ...        sign  : false,        prevX : null,        prevY : null    }}methods: {    onMouseDown($event){        this.sign = true        this.prevX = $event.offsetX        this.prevY = $event.offsetY    }}...
  • The sign property allows to know if the user has clicked on the canvas.
  • The prevX and prevY properties allow to know the current position of the cursor by retrieving it from $event.

We shift into second gear !

We will add the mousemove event to our canvas :

<template>    <canvas ... @mousemove="onMouseMove" /></template>
methods: {    ...    mousemove($event) {        if(this.sign) {            const  currX  = $event.offsetX            const  currY  = $event.offsetY        }    },}

Here we get the current position of the pointer which will allow us to draw the signature thanks to the previous position we got in the @onmousedown event.

Draw the signature

methods: {    ...    mousemove($event) {        if(this.sign) {            const  currX  = $event.offsetX            const  currY  = $event.offsetY            this.draw(this.prevX, this.prevY, currX, currY)            this.prevX  =  currX            this.prevY  =  currY        }    },    draw(depX, depY, destX, destY){        this.ctx.beginPath()        this.ctx.moveTo(depX, depY)        this.ctx.lineTo(destX, destY)        this.ctx.closePath()        this.ctx.stroke()    }}

Remarks:

  • beginPath() allows to start a path
  • moveTo() allows to initialize the starting point
  • lineTo() allows to describe the arrival point
  • closePath() closes the path
  • stroke() allows to apply the path to the canvas

Now we will prevent the user from drawing on the canvas if :

  • His cursor is outside the canvas
  • His cursor is not clicking anymore
<template>    <canvas ... @mouseup="sign = false" @mouseout="sign = false" /></template>

Get the v-model and store the canvas.

Let's define the emit update and the modelValue props

emits : ['update:modelValue'],props : {    modelValue : {        type :  null,        required :  true    }},

Let's transform our canvas drawing into an image and update the v-model in our draw method:

methods: {    ...    draw(depX, depY, destX, destY) {        this.ctx.beginPath()        this.ctx.moveTo(depX, depY)        this.ctx.lineTo(destX, destY)        this.ctx.closePath()        this.ctx.stroke()        const img = this.$el.toDataURL('image/png').replace('image/png',        'image/octet-stream')        this.$emit('update:modelValue', img)    }}

Last step !

Now we have to check if the v-model of our component is empty in order to remove our canvas drawing

watch : {    modelValue(model) {        if(!model) {            this.ctx.clearRect(0, 0, this.$el.width, this.$el.height)        }    }}

That's it!

To use our component in a parent view here is how to do it:

<template>    <MyCanvasComponent v-model="canvas" />    <button @click="canvas = null">Delete your signature</button></template>
import MyCanvasComponent from '@/components/MyCanvasComponents.vueexport default {    components : {        MyCanvasComponent    },    data(){        return {            canvas : null        }    }}

The entire component code :

<template>    <canvas @mousedown="mousedown" @mousemove="mousemove" @mouseup="sign = false" @mouseout="sign = false" /></template>
export  default {    emits : ['update:modelValue'],    props : {        modelValue : {            type :  null,            required :  true        }    },    data() {        return {            ctx :  null,            sign :  false,            prevX :  0,            prevY :  0,        }    },    methods : {        mousedown($event) {            this.sign  =  true            this.prevX  = $event.offsetX            this.prevY  = $event.offsetY        },        mousemove($event) {            if(this.sign) {                const  currX  = $event.offsetX                const  currY  = $event.offsetY                this.draw(this.prevX, this.prevY, currX, currY)                this.prevX  =  currX                this.prevY  =  currY            }        },        draw(depX, depY, destX, destY) {            this.ctx.beginPath()            this.ctx.moveTo(depX, depY)            this.ctx.lineTo(destX, destY)            this.ctx.closePath()            this.ctx.stroke()            const img = this.$el.toDataURL('image/png').replace('image/png', 'image/octet-stream')            this.$emit('update:modelValue', img)        },    },    watch : {        modelValue(model) {            if(!model) {            this.ctx.clearRect(0, 0, this.$el.width, this.$el.height)            }        }    },    mounted() {        this.ctx  = this.$el.getContext('2d')        this.ctx.strokeStyle  =  'black'        this.ctx.lineWidth  =  2    }}
<style scoped>canvas {    border: 1px solid black;    background-color: white;    cursor: crosshair;}</style>

Original Link: https://dev.to/raphbensimon/create-signature-component-in-vue-4djm

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To