思路和效果
现在几乎每个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>
随时随地看视频