Last active
August 9, 2024 14:30
-
-
Save stevebauman/cf41218606bb753bfb2e2fb788967828 to your computer and use it in GitHub Desktop.
A VueJS Signature canvas field, using szimek/signature_pad
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<canvas ref="canvas"></canvas> | |
<div class="clearfix"></div> | |
<div class="btn-group"> | |
<button @click="clear" type="button" class="btn btn-default"> | |
<i class="fa fa-times"></i> | |
Clear Signature | |
</button> | |
</div> | |
</div> | |
</template> | |
<style> | |
.signature { | |
border: 2px solid #cbc9c6; | |
border-radius: 5px; | |
} | |
</style> | |
<script> | |
import SignaturePad from 'signature_pad'; | |
export default { | |
props: { | |
value: String, | |
}, | |
data() { | |
return { | |
pad: null, | |
}; | |
}, | |
mounted() { | |
this.pad = new SignaturePad(this.$refs.canvas, { | |
onEnd: () => { | |
this.$emit('input', this.pad.toDataURL()); | |
} | |
}); | |
}, | |
methods: { | |
clear() { | |
this.pad.clear(); | |
this.$emit('input', this.pad.toDataURL()); | |
}, | |
} | |
} | |
</script> |
Thanks for that @agm1984! Do you mean inside of the onEnd
function? Or literally at the end of the mounted
function? I'll add this into the gist ๐
No I mean just after it, and I wasn't able to get the onEnd handler to work, so I just removed it.
Here's my current component (in Vue 3):
<script setup>
import { ref, onMounted } from 'vue';
import SignaturePad from 'signature_pad';
import Button from 'primevue/button';
defineProps({
modelValue: {
type: String,
required: true,
},
});
const pad = ref(null);
const emit = defineEmits(['update:model-value']);
onMounted(() => {
let canvas = document.querySelector('canvas');
pad.value = new SignaturePad(canvas, {
backgroundColor: 'rgb(255, 255, 255, 0)',
});
const ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
pad.value.clear(); // otherwise isEmpty() might return incorrect value
});
const clear = () => {
pad.value.clear();
emit('update:model-value', pad.value.toDataURL());
};
const save = () => {
const data = pad.value.toDataURL();
emit('update:model-value', data);
};
</script>
<template>
<div>
<canvas id="signature-pad" class="signature"></canvas>
<div class="flex justify-between mt-4">
<Button
type="button"
class="p-button-secondary"
label="Reset"
@click="clear"
/>
<Button
type="button"
label="Save"
@click="save"
/>
</div>
</div>
</template>
<style>
.signature {
@apply border rounded-md;
}
</style>
My usage of v-model is a bit strange, but it's still in progress, it should be plenty for someone to work with. My needs are emerging as I work with the designer to handle templates and custom signatures.
Awesome, thanks for sharing @agm1984! ๐
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code works great except the cursor draws in wack position on my MacOS + HD monitor, so I found this code which fixes it:
You'd add that at the end of your mounted lifecycle.