移动端手写签字画板——基于react-canvas-draw
2019-05-14 本文已影响0人
张Piers
公司最近的一个需求,需要在h5移动端实现上上签的电子签署的功能;
要求不依赖JQ,只能依赖react(因为h5项目使用react写的)
于是历经千辛万苦找到了一个相对适用的包react-canvas-draw
但是实际开发业务过程还是有很多不适用的地方需要调试
-
使用方法
1、安装
npm install react-canvas-draw --save
oryarn add react-canvas-draw
2、调用import React from "react"; import ReactDOM from "react-dom"; import CanvasDraw from "react-canvas-draw"; ReactDOM.render(<CanvasDraw ref={canvasDraw => (store.saveableCanvas = canvasDraw)}/>, document.getElementById("root"));
3、内部方法 参数
static defaultProps = { loadTimeOffset: 5, lazyRadius: 30, brushRadius: 12, brushColor: "#444", catenaryColor: "#0a0302", gridColor: "rgba(150,150,150,0.17)", hideGrid: false, canvasWidth: 400, canvasHeight: 400, disabled: false, imgSrc: "", saveData: null, immediateLoading: false }
getSaveData()
:返回所画的图形的canvas编码
loadSaveData(saveData: String, immediate: Boolean)
:加载savaData对应的图形
clear()
:清空画布
undo()
:撤销上一次操作
4、生成结构分析<div class="canvasBox"> <div style="display: block; background: rgb(255, 255, 255); touch-action: none; width: 375px; height: 667px;"> <canvas style="display: block; position: absolute; z-index: 15;" width="375" height="667"></canvas> <canvas style="display: block; position: absolute; z-index: 11;" width="375" height="667"></canvas> <canvas style="display: block; position: absolute; z-index: 12;" width="375" height="667"></canvas> <canvas style="display: block; position: absolute; z-index: 10;" width="375" height="667"></canvas> </div> </div>
react-canvas-draw会在代码里生成四个canvas,从上到下依次对应笔头、画布、轨迹、模版,具体功能自行选中元素尝试删除后操作画布。
-
将签字转换成图片
最终图片实际是画在第二个canvas上,也就是grid,如果需要转换成图片,将这个canvas进行转换即可
let pic = store.saveableCanvas.canvas.grid.toDataURL('image/png');
-
移动端进行手写签名时,会导致屏幕滚动
需要监听在进入这个签名页的时候,将屏幕禁止滚动;退出页面后,把禁止打开
// 进入页面后禁止滚动 document.addEventListener('touchmove', store.preventDefault, {passive: false}); // 退出后恢复滚动 window.addEventListener('popstate', (e) => { // 恢复触摸滚动页面 document.removeEventListener('touchmove', store.preventDefault, {passive: false}); }, false);
//store @action preventDefault = (e) => { e.preventDefault(); };
-
屏幕翻转,将react-canvas-draw画布横过来
屏幕大小改变的时候,屏幕宽高发生改变,但是react-canvas-draw画布的大小不会跟着改变。解决方法是监听屏幕大小改变,对画布进行相应的调整。这里有一个坑,在苹果手机上的一些浏览器不能改变画布大小,所以采用了一些兼容写法
window.addEventListener('resize', this.windowChangeEvent, {passive: false}); windowChangeEvent = () => { store.canvasWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; store.canvasHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; let bowser = this.getExploreName(); // 把对应生成的四个canvas的大小都进行修改 for(var key in store.saveableCanvas.canvas) { store.saveableCanvas.canvas[key].width = store.canvasWidth; store.saveableCanvas.canvas[key].height = store.canvasHeight; } // 兼容苹果手机上的非原生浏览器 if(window.orientation===90||window.orientation===-90){ // 横屏 if (store.canvasWidth <= store.canvasHeight || bowser === 'Unkonwn') { store.canvasWidth = window.screen.height; store.canvasHeight = window.screen.width; } }else{ // 竖屏 if (store.canvasWidth >= store.canvasHeight || bowser === 'Unkonwn') { store.canvasWidth = window.screen.width; store.canvasHeight = window.screen.height; } } } getExploreName = () => { var Sys = {}; var ua = navigator.userAgent.toLowerCase(); var s; (s = ua.match(/rv:([\d.]+)\) like gecko/)) ? Sys.ie = s[1] : (s = ua.match(/msie ([\d\.]+)/)) ? Sys.ie = s[1] : (s = ua.match(/edge\/([\d\.]+)/)) ? Sys.edge = s[1] : (s = ua.match(/firefox\/([\d\.]+)/)) ? Sys.firefox = s[1] : (s = ua.match(/(?:opera|opr).([\d\.]+)/)) ? Sys.opera = s[1] : (s = ua.match(/chrome\/([\d\.]+)/)) ? Sys.chrome = s[1] : (s = ua.match(/version\/([\d\.]+).*safari/)) ? Sys.safari = s[1] : 0; // 根据关系进行判断 if (Sys.ie) return ('IE: ' + Sys.ie); if (Sys.edge) return ('EDGE: ' + Sys.edge); if (Sys.firefox) return ('Firefox: ' + Sys.firefox); if (Sys.chrome) return ('Chrome: ' + Sys.chrome); if (Sys.opera) return ('Opera: ' + Sys.opera); if (Sys.safari) return ('Safari: ' + Sys.safari); return 'Unkonwn'; }
-
最终效果
image.png
image.png