电子签名(signature_pad)

本文最后更新于 1 年前,文中所描述的信息可能已发生改变。

signature_pad

typescript
npm i signature_pad

Based on Vue3 usage

typescript
<template>
  <div class="e-signature">
    <div class="white-board">
      <canvas ref="canvcasRef" :width="width" :height="height"> </canvas>
    </div>
    <div class="operate">
      <el-button type="primary" text bg size="small" @click="clearBoard">清除画布</el-button>
      <el-button type="primary" text bg size="small" @click="genSign">生成签名</el-button>
    </div>
  </div>
</template>
<script lang="ts" setup>
import SignaturePad from 'signature_pad'
import { onMounted, onUnmounted, ref } from 'vue'

// signature_pad 电子签名

const canvcasRef = ref<HTMLCanvasElement>()
let signaturePad: SignaturePad

const props = withDefaults(
  defineProps<{
    color: string
    width: number | string
    height: number | string
  }>(),
  {
    color: 'rgb(66, 133, 244)',
    width: 500,
    height: 300
  }
)

const emit = defineEmits<{
  genSign: [data: string]
  clear: [data: SignaturePad]
}>()

function resizeCanvas() {
  const ratio = Math.max(window.devicePixelRatio || 1, 1)
  canvcasRef.value!.width = canvcasRef.value!.offsetWidth * ratio
  canvcasRef.value!.height = canvcasRef.value!.offsetHeight * ratio
  canvcasRef.value!.getContext('2d')!.scale(ratio, ratio)
  signaturePad.clear()
}

// 生成签名base64
const genSign = () => {
  const data = signaturePad.toDataURL()
  emit('genSign', data)
}
// 清除画布
const clearBoard = () => {
  if (signaturePad.isEmpty()) {
    return
  }
  signaturePad.clear()
  emit('clear', signaturePad)
}

onMounted(() => {
  signaturePad = new SignaturePad(canvcasRef.value!, {
    maxWidth: 2,
    penColor: props.color
  })
  window.addEventListener('resize', resizeCanvas)
  resizeCanvas()
})

onUnmounted(() => {
  window.removeEventListener('resize', resizeCanvas)
})

defineExpose({
  genSign,
  clearBoard
})
</script>
<style lang="scss" scoped>
.e-signature {
  width: fit-content;
}
.white-board {
  background-color: #fdfdfd;
  width: fit-content;
  border: 1px dashed rgb(221, 221, 221);
}
.operate {
  padding: 10px;
  display: flex;
  justify-content: flex-end;
}
</style>

use

typescript
//vue
<SignFeature @genSign="genSign" ref="signRef"></SignFeature>

   // ts base的图片
   const genSign = (data: string) => {
  	signUrl.value = data
	}
View Transitions Api
js实现瀑布流