Signature Pad in Vue 3

This article will demonstrate how to create a signature pad component in Vue 3 in a few simple steps.

Step 1. Install dependencies

npm i signature_pad
npm i @vueuse/core

Step 2. Create a component

<!-- template -->

<div ref="wrapperRef" class="wrapper">
    <canvas ref="canvasRef" class="canvas"></canvas>
    <div class="label">Signature</div>
</div>
// style

.wrapper {
    position: relative;
    width: 350px;
    height: 150px;
    border-radius: 4px;
    border: 1px solid rgba(0, 0, 0, 0.24);
}

.canvas {
    cursor: crosshair;
}

.label {
    position: absolute;
    top: 10px;
    left: 12px;
    font-size: 12px;
    color: rgba(0, 0, 0, 0.6)
}

Step 3. Ensure that the canvas is always the same size as the wrapper

<!-- template -->

<canvas ref="canvasRef" class="canvas" :width="width" :height="height"></canvas>

// script

import { useElementSize } from '@vueuse/core';

const wrapperRef = ref();
const { width, height } = useElementSize(wrapperRef);

Step 4. Initialize signaturePad and configure emits

import SignaturePad from 'signature_pad';

const emit = defineEmits(['saveSignature']);

const canvasRef = ref();
const signaturePad = ref();

const saveSignature = () => {
    emit('saveSignature', signaturePad.value.toDataURL());
};

onMounted(() => {
    signaturePad.value = new SignaturePad(canvasRef.value);
    signaturePad.value.addEventListener('endStroke', saveSignature);
});

onUnmounted(() => {
signaturePad.value.removeEventListener('endStroke', saveSignature);
});

Step 5. Prevent the canvas from being cleared when its size changes

watch([width, height], async () => {
    await nextTick();
    signaturePad.value.fromData(signaturePad.value.toData());
});

Result