An Interest In:
Web News this Week
- March 21, 2024
- March 20, 2024
- March 19, 2024
- March 18, 2024
- March 17, 2024
- March 16, 2024
- March 15, 2024
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
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To