Skip to content

js+canvas 签名板

演示

<template>
    <div class="box">
        <div ref="container">
            <canvas ref="canvas"></canvas>
        </div>
        <div style="margin-top: 20px;">
            <el-button @click="clear">清空</el-button>
            <el-button @click="getBase64" type="primary">获取图片</el-button>
        </div>
    </div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
const props = withDefaults(defineProps<{
    width?: string | number;
    height?: string | number;
    lineWidth?: number;
    lineColor?: string;
    backgroundColor?: string;
}>(), {
    width: "100%",
    height: "300px",
    lineWidth: 2,
    lineColor: "#000000",
    backgroundColor: "#F6F6F6"
})

const container = ref<HTMLDivElement>();
const canvas = ref<HTMLCanvasElement>();

onMounted(() => {
    if (container.value && canvas.value) {
        // 容器和canvas的宽高设置
        container.value.style.width = (isNaN(Number(props.width)) ? props.width : `${props.width}px`) as string;
        container.value.style.height = (isNaN(Number(props.height)) ? props.height : `${props.height}px`) as string;
        const { clientWidth, clientHeight } = container.value;
        canvas.value.width = clientWidth;
        canvas.value.height = clientHeight;
        // 画布设置
        const ctx = canvas.value.getContext("2d") as CanvasRenderingContext2D;
        ctx.fillStyle = props.backgroundColor;
        ctx.fillRect(0, 0, clientWidth, clientHeight);
        ctx.lineWidth = props.lineWidth;
        ctx.lineJoin = "round";
        ctx.strokeStyle = props.lineColor;
        // 画布事件绑定
        canvas.value.onmousedown = (e) => {
            ctx.beginPath();
            ctx.moveTo(e.offsetX, e.offsetY);
            canvas.value!.onmousemove = (e) => {
                ctx.lineTo(e.offsetX, e.offsetY);
                ctx.stroke();
            };
            canvas.value!.onmouseup = () => {
                canvas.value!.onmousemove = null;
            };
            canvas.value!.onmouseleave = () => {
                canvas.value!.onmousemove = null;
            };
        };
    }
})

const clear = () => {
    const ctx = canvas.value?.getContext("2d") as CanvasRenderingContext2D;
    if (ctx) {
        ctx.clearRect(0, 0, canvas.value!.width, canvas.value!.height);
        ctx.fillStyle = props.backgroundColor;
        ctx.fillRect(0, 0, canvas.value!.width, canvas.value!.height);
    }
}

const getBase64 = () => {
    const base = canvas.value?.toDataURL() as string;
    console.log(base);
}
</script>
<style lang="scss" scoped>
.box {
    display: flex;
    flex-direction: column;
    align-items: center;
}
</style>