技术 : vue + element + canvas
实现效果
<template>
<ElDialog
:visible.sync="modal"
:close-on-click-modal="false"
title="确认金额"
width="640px"
>
<div v-if="modal" class="wrapper">
<div class="handCenter">
<h2 class="h2">
请在如下方框区域书写您的姓名
</h2>
<canvas id="handWriting" :width="canvasWidth" :height="canvasHeight">浏览器不支持canvas<!-- 如果不支持会显示这段文字 --></canvas>
</div>
</div>
<Spin v-if="loading" size="large" fix />
<div slot="footer">
<ElButton class="delBtn" type="info" @click="retDraw">
重写
</ElButton>
<ElButton class="subBtn" type="primary" @click="uploadCanvasImg">
提交
</ElButton>
</div>
</ElDialog>
</template>
<script>
export default {
components: {
//组成局部组件
},
data() {
return {
id: '',
loading: false,
modal: false,
files: [],
attachedNum: 0,
canvasName: 'handWriting',
ctx: '',
canvasWidth: 600,
canvasHeight: 280,
lineColor: '#1A1A1A', // 颜色
penWidth: 6,
penClick: false,
startAxisX: 0,
startAxisY: 0,
brackGroudColor: '#ffffff',
}
},
methods: {
// 函数
open(val) {
this.id = val
this.modal = true
this.$nextTick(() => {
this.init()
})
},
success() {
this.modal = false
this.loading = false
this.$emit('success')
},
/*======所有自定义函数======*/
init() {
let canvas = document.getElementById('handWriting') //获取canvas标签
const ctx = canvas.getContext('2d')
this.ctx = ctx
this.setCanvasBg()
/* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
canvas.addEventListener('mousemove', this.drawing) //鼠标移动事件
canvas.addEventListener('mousedown', this.penDown) //鼠标按下事件
canvas.addEventListener('mouseup', this.penUp) //鼠标弹起事件
canvas.addEventListener('mouseleave', this.penUp) //鼠标离开目标区域 防止快速移动, 鼠标离开目标区域且松开 ,但是仍然绘画的情景
},
// 笔迹移动
drawing(event) {
event.stopPropagation()
event.preventDefault()
if (!this.penClick) return
const canvas = document.getElementById('handWriting') //获取canvas标签
const ctx = canvas.getContext('2d')//创建 contextconst canvas = document.getElementById('canvas'); 对象
const stopAxisX = event.pageX
const stopAxisY = event.pageY
ctx.beginPath()
const cl = canvas.getBoundingClientRect().left
const ct = canvas.getBoundingClientRect().top
ctx.moveTo(this.startAxisX - cl, this.startAxisY - ct)//moveTo(x,y) 定义线条开始坐标
ctx.lineTo(stopAxisX - cl, stopAxisY - ct)//lineTo(x,y) 定义线条结束坐标
ctx.strokeStyle = this.lineColor
ctx.lineWidth = this.penWidth
ctx.lineCap = 'round'
ctx.stroke()// stroke() 方法来绘制线条
this.startAxisX = stopAxisX
this.startAxisY = stopAxisY
},
penDown(event) {
event.stopPropagation()
event.preventDefault()
this.penClick = true
this.startAxisX = event.pageX
this.startAxisY = event.pageY
},
penUp(e) {
this.penClick = false
e.stopPropagation()
e.preventDefault()
},
//清空
retDraw() {
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
this.setCanvasBg()
},
//判断canvas中是否有内容 新建一个空白的画布 大小背景色都相同
isCanvasBlank(canvas) {
var blank = document.createElement('canvas')
blank.width = canvas.width
blank.height = canvas.height
const ctx = blank.getContext('2d')
ctx.fillStyle = this.brackGroudColor
ctx.fillRect(0, 0, blank.width, blank.height)
return canvas.toDataURL() == blank.toDataURL()
},
//上传
async uploadCanvasImg() {
const flag = this.isCanvasBlank(document.getElementById('handWriting'))
if (flag) {
return this.$Http.msg.warning({ title: '警告', desc: '请在画板区域签名!' })
}
const canvas = document.getElementById('handWriting') //获取canvas标签
// canvas转为blob并上传,但是浏览器有兼容问题 新版chrome和firefox中能正常使用 其他浏览器报错
// 这里采用使用toDataURL()将file转成base64编码,然后转成blob
const dataURL = canvas.toDataURL()
const blob = this.base64ToBlob(dataURL)
const formData = new FormData()
// 图片ajax上传,字段名是file
formData.append('file', blob)
formData.append('fileUploadSource', 'CONFIRM_IMAGE')
try {
this.loading = true
// 开始上传 获得线上url路径
const res = await this.$Http.postFile('xxxxxx', formData, null, )
const param = {
confirmImage: res.data,
id: this.id,
}
const { code, data } = await this.$Http.postForm('xddddddd', param)
if (code == 0 && data) {//特殊场景
this.$Http.msg.warning({ title: '提示', desc: data })
}
this.success()
} catch (err) {
this.loading = false
this.$Http.msg.warning({ title: '提示', desc: err.message })
}
},
base64ToBlob(dataurl) {
var arr = dataurl.split(',')//分割为数组,分割到第一个逗号
let mime = arr[0].match(/:(.*?);/)[1]//获取分割后的base64前缀中的类型
let bstr = window.atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
},
//设置canvas背景色 不设置 导出的canvas的背景为透明
//@params:字符串 color
setCanvasBg() {
/* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
//rect() 参数说明 矩形路径左上角的横坐标,左上角的纵坐标, 矩形路径的宽度, 矩形路径的高度
//这里是 canvasHeight - 4 是因为下边盖住边框了,所以手动减了写
this.ctx.fillStyle = this.brackGroudColor
this.ctx.strokeStyle = this.lineColor
this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)
},
},
}
</script>
<style scoped>
#handWriting{
border: 2px dashed #ddd;
box-sizing: content-box;
}
.h2{
text-align: center;
margin-bottom: 10px;
}
</style>
借鉴网址: https://blog.csdn.net/Twinkle_sone/article/details/121476250