Vue E-Sign Canvas Signature Component
vue-esign is a versatile Vue.js component designed for capturing handwritten electronic signatures via an HTML Canvas element. It supports both PC and mobile environments, offering automatic canvas resizing and coordinate correction upon screen changes (window resize, device rotation). Developers can customize the canvas dimensions for the exported image, adjust stroke thickness and color, and specify the canvas background color. A key feature is the ability to crop the signature to remove surrounding whitespace, and signatures are exported as base64 encoded images, supporting `image/png`, `image/jpeg`, and `image/webp` formats. The package's current stable version is 1.1.4, which notably introduced full support for Vue 3 after a three-year update cycle, indicating a maintenance-focused release cadence with significant updates. The component differentiates itself with its responsive canvas, robust customization options, and built-in image generation capabilities, making it suitable for applications requiring digital signature capture without external dependencies.
Common errors
-
Error generating signature: Not Signned
cause The `generate()` method was called on the `vue-esign` component when no drawing or signature was present on the canvas.fixEnsure the user has interacted with the canvas and drawn a signature before attempting to generate the image. Implement error handling for the `generate()` promise to alert the user or prevent generation if the canvas is empty. -
Generated JPEG image has a black background instead of transparent
cause The JPEG image format (`image/jpeg`) does not support transparency. When a canvas is converted to JPEG, any transparent pixels are rendered as black.fixIf transparency is required, use `image/png` or `image/webp` for the `format` option in the `generate()` method. Alternatively, if JPEG is mandatory, provide a specific `bgColor` prop to the `vue-esign` component to define a non-transparent background color for the canvas.
Warnings
- breaking The `bgColor` prop binding syntax changed for Vue 3 compatibility. In Vue 2, it used the `.sync` modifier (`:bgColor.sync`).
- gotcha When exporting to `image/jpeg` format, transparent areas of the canvas will be rendered as black, as JPEG does not support transparency.
- gotcha The `generate()` method will reject its promise with an error (e.g., 'Not Signned') if called on an empty canvas where no signature has been drawn.
Install
-
npm install vue-esign -
yarn add vue-esign -
pnpm add vue-esign
Imports
- VueEsign (default export)
import { VueEsign } from 'vue-esign'import VueEsign from 'vue-esign'
- VueEsign (global plugin)
const VueEsign = require('vue-esign'); Vue.use(VueEsign);import VueEsign from 'vue-esign'; const app = createApp(App); app.use(VueEsign);
- VueEsign (local component)
import { VueEsign } from 'vue-esign'; export default { components: { VueEsign } }import VueEsign from 'vue-esign'; export default { components: { VueEsign } }
Quickstart
<!-- App.vue (or a component file) -->
<script setup lang="ts">
import { ref } from 'vue';
import VueEsign from 'vue-esign';
const esignRef = ref<InstanceType<typeof VueEsign> | null>(null);
const lineWidth = ref(6);
const lineColor = ref('#000000');
const bgColor = ref('');
const resultImg = ref('');
const isCrop = ref(false);
const isClearBgColor = ref(true);
const handleReset = () => {
if (esignRef.value) {
esignRef.value.reset();
resultImg.value = ''; // Clear previous result on reset
}
};
const handleGenerate = async () => {
if (esignRef.value) {
try {
const res = await esignRef.value.generate({
format: 'image/png',
quality: 1
});
resultImg.value = res;
console.log('Generated base64 image (truncated):', res.substring(0, 50) + '...');
} catch (err: any) {
alert(`Error generating signature: ${err.message || err}`);
}
}
};
</script>
<template>
<div style="max-width: 800px; margin: 20px auto; border: 1px solid #eee; padding: 20px;">
<h2>Vue E-Sign Demo</h2>
<p>Sign below:</p>
<vue-esign
ref="esignRef"
:width="800"
:height="300"
:isCrop="isCrop"
:lineWidth="lineWidth"
:lineColor="lineColor"
v-model:bgColor="bgColor"
:isClearBgColor="isClearBgColor"
style="border: 1px dashed #ccc;"
/>
<div style="margin-top: 20px;">
<button @click="handleReset" style="margin-right: 10px; padding: 8px 15px;">Clear Signature</button>
<button @click="handleGenerate" style="padding: 8px 15px; background-color: #4CAF50; color: white; border: none;">Generate Image</button>
</div>
<div v-if="resultImg" style="margin-top: 20px;">
<h3>Generated Signature:</h3>
<img :src="resultImg" alt="Generated Signature" style="max-width: 100%; border: 1px solid #ccc;"/>
<p style="font-size: 0.8em; word-break: break-all;">Base64 output (truncated): {{ resultImg.substring(0, 100) }}...</p>
</div>
<div style="margin-top: 20px; border-top: 1px solid #eee; padding-top: 15px;">
<h4>Configuration:</h4>
<p>Line Width: <input type="number" v-model="lineWidth" /></p>
<p>Line Color: <input type="color" v-model="lineColor" /></p>
<p>Background Color: <input type="text" v-model="bgColor" placeholder="e.g., #f0f0f0, transparent" /></p>
<p>Crop Signature: <input type="checkbox" v-model="isCrop" /></p>
<p>Clear Background Color on Reset: <input type="checkbox" v-model="isClearBgColor" /></p>
</div>
</div>
</template>