思路和效果
现在几乎每个app应用都会有手势解锁这一功能,微信支付宝等关键操作的时候都会转到手势解锁,想要在手势解锁这个功能上出彩的话,必须要自己来实现才能个性化的进行手势解锁。比如现在都是9个点画出的图形可能会简单,能被别人轻易试出密码,如果换成30个点那样画出的图形就会相当复杂了,可以增加手势密码的复杂度。另外自己可以指定其各种元素的颜色、线条的粗细等,都可以达到令人耳目一新的效果。本例是在移动端实现的
思路:
效果:
代码实现
<html> <head> <style> * { margin: 0px; padding: 0px; user-select: none; } canvas { cursor: pointer; width: 300px; height: 300px; } </style> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <canvas id="canvas" width="600" height="600"></canvas> </body> <script> // 获取canvas对象 var canvas = document.getElementById("canvas"); // 手指是否按下 var IStouchdown = false; // 设置画布宽度-是样式宽度的两倍,为了适应移动端的设备像素比 canvas.width = window.innerWidth * 2 // 设置画布高度 canvas.height = window.innerWidth * 2 // 设置画布的样式宽度 canvas.style.width = window.innerWidth + "px"; // 设置画布的样式高度 canvas.style.height = window.innerWidth + "px"; // 获取画布宽度 var width = canvas.width; // 获取画布高度 var height = canvas.height; // 获取画布上下文 var cxt = canvas.getContext("2d"); // 指定画布拐角的样式 cxt.lineJoin = "round"; // 画圆点 宽高都化为4份 确定圆点的间距 // 定义点的数组 var dotArr = []; // 定义横向的间距 var dotSpaceX = Math.round(width / 4); // 定义纵向的间距 var dotSpaceY = Math.round(height / 4); // 鼠标经过圆点时自动吸附的距离 var adsorbSpace = width / 20; // 定义计数器,用于嵌套循环的计数 var index = 1; for (var i = 1; i <= 3; i++) { for (var j = 1; j <= 3; j++) { index++ dotArr.push({ // 横坐标 x: i * dotSpaceX, // 纵坐标 y: j * dotSpaceY, // 是否已经被连线 isLink: false, // 数字 num: index }); } index++ } // 圆点的半径的大小 var pieRadius = width / 12; // 定义路径的点的集合 var path = []; drawPie(); // 绘制9个圆形 function drawPie() { for (var k = 0; k < dotArr.length; k++) { var item = dotArr[k]; // 开始一条路径,或重置当前的路径 cxt.beginPath(); // 定义路径的样式 cxt.strokeStyle = "gray"; // 定义路径的宽度 cxt.lineWidth = "2"; // 画圆形 cxt.arc(item.x, item.y, pieRadius, 0, Math.PI * 2, true); // 创建从当前点到开始点的路径 cxt.closePath(); // 在画布上绘制确切的路径 cxt.stroke(); } } // 监听画布上手指按下 canvas.addEventListener("touchstart", function(e) { // 手指按下 IStouchdown = true; // 开始一条路径,或重置当前的路径 cxt.beginPath(); draw(e) }, false) // 监听画布上手指移动 canvas.addEventListener("touchmove", function(e) { draw(e) e.preventDefault(); }, false) // 监听屏幕手指抬起-手指抬起的地方可能是画布之外 document.addEventListener("touchend", function(e) { // 手指抬起 IStouchdown = false; // 清空画布 clear(); // 重新绘制圆 drawPie(); // 定义密码字段 var pass = "" // 绘制路径 for (var k = 0; k < path.length; k++) { cxt.strokeStyle = "green"; cxt.lineWidth = "3"; cxt.lineTo(path[k].x, path[k].y); cxt.stroke(); // 密码拼接字符串 pass += path[k]["num"] + "" } // 绘制亮点 for (var k = 0; k < path.length; k++) { cxt.beginPath(); cxt.fillStyle = "green"; cxt.strokeStyle = "green"; cxt.arc(path[k].x, path[k].y, pieRadius / 4, 0, Math.PI * 2, true); cxt.closePath(); cxt.fill(); cxt.stroke(); } // 判断密码是否正确 if ("26101112" == pass) { setTimeout(function() { alert("解锁成功") }) } else { // 如果不正确,清空画布重新绘制九个圆 clear(); drawPie(); setTimeout(function() { alert("解锁失败") }) // 初始化path数组和圆点的缓存数组 path = []; for (var k = 0; k < dotArr.length; k++) { var item = dotArr[k]; item.isLink = false; } } }, false) // 清空画布 function clear() { cxt.clearRect(0, 0, width, height); } // 绘制路径 function draw(e) { // 手指按下的情况 if (IStouchdown) { // 获取手指在画布上按下的或移动的点--乘以2也是处理设备像素比 var x = (e.touches[0]["clientX"] - e.target.offsetLeft) * 2; var y = (e.touches[0]["clientY"] - e.target.offsetTop) * 2; // 循环九个圆形 for (var i = 0; i < dotArr.length; i++) { var item = dotArr[i]; // 判断点与手指按下的点的距离是否在吸附距离之内 if (Math.abs(item.x - x) < adsorbSpace && Math.abs(item.y - y) < adsorbSpace) { // 如果圆点在没有被连接的情况 if (!dotArr[i]["isLink"]) { // 圆点存入路径数组 path.push(item); // isLink属性改为true dotArr[i]["isLink"] = true; } } } // 清空画布 clear(); // 重新绘制圆 drawPie(); // 根据路径中圆点 绘制绿色的圆 制造点亮的效果 for (var k = 0; k < path.length; k++) { cxt.beginPath(); cxt.fillStyle = "green"; cxt.arc(path[k].x, path[k].y, pieRadius / 4, 0, Math.PI * 2, true); cxt.closePath(); cxt.fill(); } cxt.beginPath(); // 根据圆心绘制手指经过的路径 for (var k = 0; k < path.length; k++) { cxt.strokeStyle = "green"; cxt.lineWidth = "3"; cxt.lineTo(path[k].x, path[k].y); cxt.stroke(); } cxt.strokeStyle = "green"; cxt.lineWidth = "3"; // 手指移动中的点 cxt.lineTo(x, y); cxt.stroke(); } } </script> </html>