您现在的位置是:网站首页> 编程资料编程资料
h5使用canvas画布实现手势解锁解锁canvas导出图片跨域的N种姿势小结html5 canvas手势解锁源码分享
2021-08-31
1215人已围观
简介 这篇文章主要介绍了h5使用canvas画布实现手势解锁的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
前言
最近做的一个app项目使用的 apicloud 来实现跨平台开发,现在需要为这个 app 添加手势(九宫格)解锁的功能,apicloud 已经有一些第三方的原生实现的手势解锁插件,因为是原生的性能也比较好,调用也比较方便,但是都不能对它们的样式做修改,所以就打算自己来实现这个功能。这篇文章将实现过程整理分享出来,希望有需要的可以了解。分享出来的代码只实现了最基本的 设置密码功能 、 解锁功能 、 比较密码 的功能等,一些高级功能例如:不能限制一个点最多经过多少次、限制用户设置密码的长度。

原生实现还是其它方式实现?
1、使用 android 和 ios 对应的平台通过原生代码来写手势解锁插件。体验好,但是开发周期长,需要处理各平台的兼容性问题,并且需要学习apicloud平台插件编写方法。(放弃)
2、使用 html5 的 canvas 画布来实现。开发周期短,不需要过多的处理兼容性问题,体验好。(选择)
原理分析

手势解锁
通过手指将屏幕上的九个点依次连接起来形成一个图案,所以叫图案解锁。如上图每一个解锁圆圈后面其实都是一个数字,每次比较的并不是是用户画出来的图案,而是每次手指经过图案时串联起来的圆圈下的数字组成的密码字符串,本质上我们比较的还是字符串的密码,只不过站在用户的角度看是绘制出来的图案。图案的记忆远比数字字符串记的牢固。
实现步骤
绘制密码盘
密码盘的绘制比较简单,唯一需要注意需要通过动态计算使九个点围成的正方式始终在屏幕的中间位置,在手机上还需要减去状态栏的高度。
var width = $(document).width(); var height = $(document).height() - 40; //减去手机状态栏的高度 //九宫格其实就是九个点,9个点的坐标对象 var lockCicle = { x: 0, //x坐标 y: 0, //y坐标 color: "#999999", state: "1" //状态当前点是否已经被链接过 }; var offset = (width - height) / 2; //计算偏移量 var arr = []; //九个点的坐标数组 //计算九个点坐标的方法 for (var i = 1; i <= 3; i++) { //每一行 for (var j = 1; j <= 3; j++) { //每一行的每一个 var lockCicle = {}; //横屏 if (offset > 0) { lockCicle.x = (height / 4) * j + Math.abs(offset); lockCicle.y = (height / 4) * i; lockCicle.state = 0; //竖屏 } else { lockCicle.x = (width / 4) * j; lockCicle.y = (width / 4) * i + Math.abs(offset); lockCicle.state = 0; } arr.push(lockCicle); } } //初始化界面的方法 function init() { ctx.clearRect(0, 0, width, height); //清空画布 pointerArr = []; //清楚绘制路径 for (var i = 0; i < arr.length; i++) { arr[i].state = 0; //清除绘制状态 drawPointer(i); } } //绘制九宫格解锁界面 function drawPointer(i) { ctx.save(); var radius = 0; if (hastouch) { radius = width / 12; } else { radius = 24; } var _fillStyle = "#dd514c"; var _strokeStyle = "#dd514c"; //不同状态显示不同颜色 if (arr[i].state == 1) { _strokeStyle = "#1bd6c5"; } //绘制原点 ctx.beginPath(); ctx.fillStyle = _fillStyle; ctx.arc(arr[i].x, arr[i].y, 6, 0, Math.PI * 2, false); ctx.fill(); ctx.closePath(); //绘制圆圈 ctx.beginPath(); ctx.strokeStyle = _strokeStyle; ctx.lineWidth = 0.3; ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.arc(arr[i].x, arr[i].y, radius, 0, Math.PI * 2, false); ctx.stroke(); ctx.closePath(); ctx.restore(); } //初始化界面 init();绘制连线
绘制连线的方法
var pointerArr = []; //连接线点的坐标数组 var startX, startY; //线条起始点 var puts = []; //经过的九个点的数组 var currentPointer; //当前点是否已经连接 var pwd = []; //密码 var confirmPwd = []; //确认密码 var unlockFlag = false; //是否解锁的标志 /** ** 绘制链接线的方法,将坐标数组中的点绘制在canvas画布中 **/ function drawLinePointer(x, y, flag) { ctx.clearRect(0, 0, width, height); ctx.save(); ctx.beginPath(); ctx.strokeStyle = "#1bd6c5"; ctx.lineWidth = 5; ctx.lineCap = "round"; ctx.lineJoin = "round"; for (var i = 0; i < pointerArr.length; i++) { if (i == 0) { ctx.moveTo(pointerArr[i].x, pointerArr[i].y); } else { ctx.lineTo(pointerArr[i].x, pointerArr[i].y); } } ctx.stroke(); ctx.closePath(); ctx.restore(); for (var i = 0; i < arr.length; i++) { drawPointer(i); //绘制圆圈和原点 if (ctx.isPointInPath(x, y) && currentPointer != i) { //判断鼠标点击是否在圆中 pointerArr.push({ x: arr[i].x, y: arr[i].y }); currentPointer = i; puts.push(i + 1); startX = arr[i].x; startY = arr[i].y; arr[i].state = 1; } } if (flag) { ctx.save(); ctx.beginPath(); ctx.globalCompositeOperation = "destination-over"; ctx.strokeStyle = "#e2e0e0"; ctx.lineWidth = 5; ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.moveTo(startX, startY); ctx.lineTo(x, y); ctx.stroke(); ctx.beginPath(); ctx.restore(); } }绑定事件
连线的过程就是将 3 个 touch(移动端) 事件组合起来获取当前位置的坐标放入数组中,然后将这些坐标渲染到界面上的过程。
- touchstart (mousedown) 当手指(鼠标)按下时设置 isMouseDown=true,同时将该点的坐标保存到线条数组中,并将数组中的点绘制出来。
- touchmove (mousemove) 当 isMouseDown=true 时 将手指(鼠标)移动过程中所有的坐标点都保存到萧条数组中,并将数组中的点绘制出来。
- mouseup (mouseup) 当手指(鼠标)松开后设置 isMouseDown=fasle.将数组中的所有点绘制出来,清空 pointerArr 数组,然后比较连接的点的数量如果小于 6(自己设置,一般密码 6 位以上)给一个密码长度不够的提示,清空 puts 数组,重新调用 init 方法初始化界面,如果大于等于 6 则密码设置成功。
//兼容移动触摸的事件写法 var hastouch = "ontouchstart" in window ? true : false, tapstart = hastouch ? "touchstart" : "mousedown", tapmove = hastouch ? "touchmove" : "mousemove", tapend = hastouch ? "touchend" : "mouseup"; //绑定按下事件 lockCnavs.addEventListener(tapstart, function(e) { isMouseDown = true; var x1 = hastouch ? e.targetTouches[0].pageX : e.clientX - canvas.offsetLeft; var y1 = hastouch ? e.targetTouches[0].pageY : e.clientY - canvas.offsetTop; drawLinePointer(x1, y1, true); }); //移动时候,将经过的坐标点全部保存起来 lockCnavs.addEventListener(tapmove, function(e) { if (isMouseDown) { var x1 = hastouch ? e.targetTouches[0].pageX : e.clientX - canvas.offsetLeft; var y1 = hastouch ? e.targetTouches[0].pageY : e.clientY - canvas.offsetTop; drawLinePointer(x1, y1, true); } }); //取消 lockCnavs.addEventListener(tapend, function(e) { drawLinePointer(0, 0, false); isMouseDown = false; pointerArr = []; if (puts.length >= 6) { alert("你的图案密码是: [ " + puts.join(" > ") + " ]"); if (unlockFlag) { //解锁 unlock(); } else { //设置解锁密码 settingUnlockPwd(); } } else { if (puts.length >= 1) { alert("你的图案密码太简单了~~~"); init(); } } puts = []; });实现解锁逻辑
通过上面几步的操作,九宫格解锁每一次绘图之后的数据和显示效果都有了,现在只需要在关键地方添加相应逻辑代码就可以了,这里主要介绍它的实现逻辑就不对代码做封装了。
相关代码
//设置解锁密码和解锁测试 function settingUnlockPwd() { if (pwd.length <= 0) { pwd = puts; init(); $("header").text("再次绘制解锁图案"); } else if (confirmPwd.length <= 0) { confirmPwd = puts; } console.log(pwd + " " + confirmPwd); //笔记两次密码是否正确 if (pwd.length > 0 && confirmPwd.length > 0) { if (compareArr(pwd, confirmPwd)) { $("header").text("解锁图案绘制成功"); init(); } else { $("header").text("两次绘制的解锁图案不一致"); init(); confirmPwd = []; } } } //解锁 function unlock() { console.log("解锁密码:" + puts + " " + confirmPwd); if (compareArr(puts, confirmPwd)) { $("header").text("解锁成功!页面跳转中......"); } else { $("header").text("解锁图案不正确!!!"); init(); } } $("footer").click(function() { if ($(this).text() === "解锁") { unlockFlag = true; init(); $("header").text("绘制解锁图案"); } }); //比较两个数组(Number)是否相等 function compareArr(arr1, arr2) { return arr1.toString() === arr2.toString(); }后记
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
相关内容
- canvas中普通动效与粒子动效的实现代码示例详解Canvas 实现炫丽的粒子运动效果(粒子生成文字)
- 详解webapp页面滚动卡顿的解决办法html5实现点击弹出图片功能html5 录制mp3音频支持采样率和比特率设置html5表单的required属性使用html5调用摄像头实例代码HTML5页面音频自动播放的实现方式Html5大屏数据可视化开发的实现html实现弹窗的实例HTML5来实现本地文件读取和写入的实现方法HTML 罗盘式时钟的实现HTML5简单实现添加背景音乐的几种方法
- Html5调用手机摄像头并实现人脸识别的实现html5调用摄像头功能的实现代码HTML5混合开发二维码扫描以及调用本地摄像头HTML5调用手机摄像头拍照的实现思路及代码HTML5 Canvas+JS控制电脑或手机上的摄像头实例html5调用摄像头实例代码
- JavaScript+Canvas实现自定义画板的示例代码几何画板怎么利用弧绘制三角形折叠?几何画板怎么制作旋转的正六边形课件?几何画板怎么一只飞舞的蝴蝶动画?手把手教你实现一个canvas智绘画板的方法ai怎么设置画板属性? ai画板设置属性的教程金排物理画板 V2019 中文免费安装版socket.io 和canvas 实现的共享画板功能
- 使用html5实现表格实现标题合并的实例代码html5实现点击弹出图片功能html5 录制mp3音频支持采样率和比特率设置html5表单的required属性使用html5调用摄像头实例代码HTML5页面音频自动播放的实现方式Html5大屏数据可视化开发的实现html实现弹窗的实例HTML5来实现本地文件读取和写入的实现方法HTML 罗盘式时钟的实现HTML5简单实现添加背景音乐的几种方法
- 基于Html5实现的语音搜索功能HTML5实时语音通话聊天MP3压缩传输3KB每秒使用Html5多媒体实现微信语音功能鲜为人知的HTML5语音合成功能HTML5为输入框添加语音输入功能的实现方法Jquery+html5可设置闹钟并且会语音提醒的时钟特效源码用html5实现语音搜索框的方法HTML5语音识别标签写法附图html5的新玩法——语音搜索HTML5 语音搜索只需一句代码HTML5 语音搜索(淘宝店语音搜素)
- 怎样实现H5+CSS3手指滑动切换图片的示例代码css实现导航切换的实例代码用CSS实现Tab页切换效果的示例代码CSS实现Tab页切换实例代码CSS使用classList实现两个按钮样式的切换纯CSS3制作页面切换效果的实例代码
- 详解使用双缓存解决Canvas clearRect引起的闪屏问题用HTML5 Canvas API中的clearRect()方法实现橡皮擦功能
- 浅谈HTML5新增和废弃的标签HTML5新标签兼容——> <!--<if lt IE 9><!endif--> HTML5新增的标签和属性归纳总结详解HTML5新增标签HTML5新特性之语义化标签常用的HTML5列表标签HTML5的文档结构和新增标签完全解析HTML5文档结构标签Html5新增标签有哪些HTML5标签大全HTML5新增加标签和功能概述
- 可能这些是你想要的H5软键盘兼容方案(小结)HTML5 虚拟键盘出现挡住输入框的解决办法利用HTML5 Canvas制作键盘及鼠标动画的实例分享HTML5 Canvas鼠标与键盘事件demo示例
