vue h5移动端使用canvas实现手写签名并生成png图片,支持修改画笔颜色和画笔粗细,画布颜色及宽高(附完整代码)

时间:2024-11-24 06:56:47
  • <template>
  • <canvas id="canvas" :width="canvasWidth" :height="canvasHeight" :style="`background:${canvasBackgroung}`"></canvas>
  • </template>
  • <script>
  • /**
  • * @canvasWidth : 画布宽度 type: Number
  • * @canvasHeight : 画布高度 type: Number
  • * @canvasBackgroung : 画布颜色 type: String, 颜色值
  • * @lineWidth : 画笔粗细 type: Number
  • * @stokeColor : 画笔颜色 type: String, 颜色值
  • * save() : url: base64格式图片,file:png图片文件 调用保存方法并返回签名图片文件及base64格式图片
  • * clear() : 清除画板
  • */
  • var draw;
  • var preHandler = function(e) {
  • e.preventDefault(); //阻止默认事件
  • };
  • class Draw {
  • constructor(el) {
  • this.el = el;
  • this.canvas = document.getElementById(this.el);
  • this.cxt = this.canvas.getContext("2d"); //设置绘图环境为2D
  • canvas.width = canvas.offsetWidth;
  • canvas.height = canvas.offsetHeight;
  • this.stage_info = canvas.getBoundingClientRect(); //用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置
  • this.path = {
  • beginX: 0,
  • beginY: 0,
  • endX: 0,
  • endY: 0
  • };
  • }
  • init(btn) {
  • var that = this;
  • this.canvas.addEventListener("touchstart", function(event) { //给canvas添加触摸开始事件
  • document.addEventListener("touchstart", preHandler, false); //当点击画布进行绘制时,禁止canvas外部默认事件
  • that.drawBegin(event);
  • });
  • this.canvas.addEventListener("touchend", function(event) { //给canvas添加触摸结束事件
  • document.addEventListener("touchend", preHandler, false); //当触摸离开时,禁止canvas外部默认事件
  • that.drawEnd();
  • });
  • this.clear(btn); //清除画布
  • }
  • drawBegin(e) {
  • var that = this;
  • window.getSelection() //双击禁止选中文字 || (),返回一个Selection对象,表示用户选择的文本范围或光标的当前位置。
  • ? window.getSelection().removeAllRanges() //将所有的区域都从选区中移除
  • : document.selection.empty(); //让选中的内容不选中
  • this.cxt.beginPath(); //起始一条路径,或重置当前路径
  • this.cxt.moveTo( //把路径移动到画布中的指定点,不创建线条
  • e.changedTouches[0].clientX - this.stage_info.left,
  • e.changedTouches[0].clientY - this.stage_info.top
  • );
  • this.path.beginX = e.changedTouches[0].clientX - this.stage_info.left;
  • this.path.beginY = e.changedTouches[0].clientY - this.stage_info.top;
  • canvas.addEventListener("touchmove", function() {
  • that.drawing(event);
  • });
  • }
  • drawing(e) {
  • this.cxt.lineTo( //添加一个新点,然后在画布中创建从该点到最后指定点的线条
  • e.changedTouches[0].clientX - this.stage_info.left,
  • e.changedTouches[0].clientY - this.stage_info.top
  • );
  • this.path.endX = e.changedTouches[0].clientX - this.stage_info.left;
  • this.path.endY = e.changedTouches[0].clientY - this.stage_info.top;
  • this.cxt.stroke(); //绘制已定义的路径
  • }
  • drawEnd() {
  • document.removeEventListener("touchstart", preHandler, false); //触摸开始时移除阻止默认事件
  • document.removeEventListener("touchend", preHandler, false); //触摸结束时移除阻止默认事件
  • document.removeEventListener("touchmove", preHandler, false); //手指在屏幕上移动时移除阻止默认事件
  • }
  • clear(btn) {
  • this.cxt.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight); //在给定的矩形内清除指定的像素
  • }
  • save() {
  • let url = canvas.toDataURL("image/png") //base64格式的签名图片文件
  • let file = this.dataURLtoFile(url) //base64转换后获得的签名图片文件
  • let imgData = {
  • url,
  • file
  • }
  • return imgData
  • }
  • //将base64转换为文件
  • dataURLtoFile(dataurl, filename) {
  • let arr = dataurl.split(',') //得到base64后面的文件数据
  • let mime = arr[0].match(/:(.*?);/)[1]; //得到文件类型 image/png
  • if(!filename) {//若无文件名则取当前时间戳
  • filename = Date.parse(new Date()) + '.png';
  • }
  • let bstr = atob(arr[1]) //将base64文件数据进行解码
  • let n = bstr.length //得到解码后数据的长度
  • let u8arr = new Uint8Array(n);
  • while(n--){
  • u8arr[n] = bstr.charCodeAt(n);
  • }
  • return new File([u8arr], filename, {type:mime});
  • }
  • }
  • export default {
  • props: {
  • canvasWidth: {
  • type: Number,
  • default: 0
  • },
  • canvasHeight: {
  • type: Number,
  • default: 0
  • },
  • canvasBackgroung: {
  • type: String,
  • default: '#fff'
  • },
  • lineWidth: {
  • type: Number,
  • default: 1
  • },
  • stokeColor: {
  • type: String,
  • default: 'black'
  • }
  • },
  • data () {
  • return {
  • url: "", //签名的base64格式
  • imgFile:'', //签名图片文件
  • }
  • },
  • mounted() {
  • draw = new Draw("canvas");
  • draw.cxt.strokeStyle = this.stokeColor; //画笔颜色
  • draw.cxt.lineWidth = this.lineWidth; //画笔粗细
  • draw.init();
  • },
  • methods: {
  • //清除签名画板
  • clear: function() {
  • draw.clear();
  • },
  • //获取到签名文件
  • save: function() {
  • var data = draw.save();
  • this.url = data.url; //base64格式的签名图片
  • this.imgFile = data.file //签名的图片文件
  • return data;
  • },
  • }
  • }
  • </script>
  • <style lang="scss" scoped>
  • #canvas {
  • touch-action: none; //去掉滑动的默认样式
  • cursor: default; //鼠标样式为默认样式
  • }
  • </style>