先放图

demo.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>手势解锁</title>
<style type="text/css">
body{
text-align: center;
background: #305066;
}
h4{
color: #22C3AA;
}
</style>
</head>
<body>
<script type="text/javascript" src="src/index.js"></script>
<script type="text/javascript">
// 1、生成背景
// 2、title生成
// 3、用js动态生成canvas标签
// 4、js方式动态生成h4标签和canvas标签
new canvasLock({chooseType:3}).init();
</script>
</body>
</html>

index.js

(function(){
/**
* 实现画圆和划线:
* 1、添加事件touchstart、touchmove、touchend
* 2、touchstart判断是否点击的位置处于圆内getPosition,处于则初始化
* lastpoint、restPoint
* 3、touchmove做的就是:画圆drawPoint和画线drawLine
*
* 实现自动画圆的效果
* 1、检测手势移动的位置是否处于圆内
* 2、圆内的话则画圆 drawPoint
* 3、已经画过实心圆的圆,无需重复检测
*
* 实现解锁成功:
* 1、检测路径是否是对的
* 2、如果是对的就重置,圆圈变绿
* 3、不对也重置,圆圈变红
* 4、重置
*/ window.canvasLock = function(obj){
this.height = obj.height;
this.width = obj.width;
this.chooseType = obj.chooseType;
}; // js方式动态生成dom
canvasLock.prototype.initDom = function(){
var wrap = document.createElement('div');
var str = '<h4 id="title" class="title">绘制解锁图案</h4>';
wrap.setAttribute('style','position: absolute;top:0;left:0;right:0;bottom:0;'); var canvas = document.createElement('canvas');
canvas.setAttribute('id','canvas');
canvas.style.cssText = 'background-color: #305066;display: inline-block;margin-top: 15px;'; wrap.innerHTML = str;
wrap.appendChild(canvas); var width = this.width || 300;
var height = this.height || 300; document.body.appendChild(wrap); // 高清屏锁放
canvas.style.width = width + "px";
canvas.style.height = height + "px"; canvas.width = width;
canvas.height = height; }
canvasLock.prototype.drawCle = function(x, y) { // 初始化解锁密码面板
this.ctx.strokeStyle = '#CFE6FF';
this.ctx.lineWidth = 2;
this.ctx.beginPath();
this.ctx.arc(x, y, this.r, 0, Math.PI * 2, true);
this.ctx.closePath();
this.ctx.stroke();
}
canvasLock.prototype.createCircle = function() {// 创建解锁点的坐标,根据canvas的大小来平均分配半径 var n = this.chooseType;
var count = 0;
this.r = this.ctx.canvas.width / (2 + 4 * n);// 公式计算
this.lastPoint = [];
this.arr = [];
this.restPoint = [];
var r = this.r;
for (var i = 0 ; i < n ; i++) {
for (var j = 0 ; j < n ; j++) {
count++;
var obj = {
x: j * 4 * r + 3 * r,
y: i * 4 * r + 3 * r,
index: count
};
this.arr.push(obj);
this.restPoint.push(obj);
}
} this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
for (var i = 0 ; i < this.arr.length ; i++) {
// 画圆函数
this.drawCle(this.arr[i].x, this.arr[i].y);
}
//return arr;
} // 程序初始化
canvasLock.prototype.init = function() {
this.initDom();
this.canvas = document.getElementById('canvas');
this.ctx = this.canvas.getContext('2d');
this.touchFlag = false;
// 1、确定半径
// 2、确定每一个圆的中心坐标点
// 3、一行3个圆14个半径,一行4个圆有18个半径
this.createCircle();
this.bindEvent();
} canvasLock.prototype.bindEvent = function(){
var self = this;
this.canvas.addEventListener("touchstart", function (e) {
// 2、touchstart判断是否点击的位置处于圆内getPosition,处于则初始化
// * lastpoint、restPoint // po有x和y,并且是相较于canvas边距
var po = self.getPosition(e);
console.log(po.x)
// 判断是否在圆内的原理:多出来的这条 x/y < r 在圆内
for (var i = 0 ; i < self.arr.length ; i++) {
if (Math.abs(po.x - self.arr[i].x) < self.r && Math.abs(po.y - self.arr[i].y) < self.r) { self.touchFlag = true; // lastPoint存放的就是选中的圆圈的x/y坐标值
self.lastPoint.push(self.arr[i]); self.restPoint.splice(i,1);
break;
}
} }, false); this.canvas.addEventListener("touchmove", function (e) { // touchmove做的就是:画圆drawPoint和划线drawLine
if (self.touchFlag) {
self.update(self.getPosition(e));
}
}, false); this.canvas.addEventListener("touchend", function(e){
if (self.touchFlag) {
self.storePass(self.lastPoint);
setTimeout(function(){
self.reset();
}, 300);
}
}, false);
} canvasLock.prototype.getPosition = function(e) {// 获取touch点相对于canvas的坐标
var rect = e.currentTarget.getBoundingClientRect();
var po = {
x: (e.touches[0].clientX - rect.left),
y: (e.touches[0].clientY - rect.top)
};
return po;
} canvasLock.prototype.update = function(po) {// 核心变换方法在touchmove时候调用
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); // 重新画9个圆圈
for (var i = 0 ; i < this.arr.length ; i++) { // 每帧先把面板画出来
this.drawCle(this.arr[i].x, this.arr[i].y);
} this.drawPoint();// 画圆
this.drawLine(po);// 画线 // 1、检测手势移动的位置是否处于下一个圆内
// 2、圆内的话则画圆 drawPoint
// 3、已经画过实心圆的圆,无需重复检测
for (var i = 0 ; i < this.restPoint.length ; i++) {
if (Math.abs(po.x - this.restPoint[i].x) < this.r && Math.abs(po.y - this.restPoint[i].y) < this.r) {
this.drawPoint();
this.lastPoint.push(this.restPoint[i]);
this.restPoint.splice(i, 1);
break;
}
} console.log(this.lastPoint) }
canvasLock.prototype.drawLine = function(po) {// 解锁轨迹
this.ctx.beginPath();
this.ctx.lineWidth = 3;
this.ctx.moveTo(this.lastPoint[0].x, this.lastPoint[0].y);
for (var i = 1 ; i < this.lastPoint.length ; i++) {
this.ctx.lineTo(this.lastPoint[i].x, this.lastPoint[i].y);
}
this.ctx.lineTo(po.x, po.y);
this.ctx.stroke();
this.ctx.closePath();
}
canvasLock.prototype.drawPoint = function() { // 初始化圆心
for (var i = 0 ; i < this.lastPoint.length ; i++) {
this.ctx.fillStyle = '#CFE6FF';
this.ctx.beginPath();
this.ctx.arc(this.lastPoint[i].x, this.lastPoint[i].y, this.r / 2, 0, Math.PI * 2, true);
this.ctx.closePath();
this.ctx.fill();
}
} // 1、检测路径是否是对的
// 2、如果是对的就重置,圆圈变绿
// 3、不对也重置,圆圈变红
// 4、重置
canvasLock.prototype.storePass = function() {
if (this.checkPass()) {
document.getElementById('title').innerHTML = '解锁成功';
this.drawStatusPoint('#2CFF26');
}else{
document.getElementById('title').innerHTML = '解锁失败';
this.drawStatusPoint('red');
}
}
canvasLock.prototype.checkPass = function() {
var p1 = '123',
p2 = '';
for (var i = 0 ; i < this.lastPoint.length ; i++) {
p2 += this.lastPoint[i].index;
}
return p1 === p2;
}
canvasLock.prototype.drawStatusPoint = function(type) {
for (var i = 0 ; i < this.lastPoint.length ; i++) {
this.ctx.strokeStyle = type;
this.ctx.beginPath();
this.ctx.arc(this.lastPoint[i].x, this.lastPoint[i].y, this.r, 0, Math.PI * 2, true);
this.ctx.closePath();
this.ctx.stroke();
}
}
canvasLock.prototype.reset = function(){
this.createCircle();
}
})();

canvas手势解锁源码的更多相关文章

  1. 缩放手势 ScaleGestureDetector 源码解析,这一篇就够了

    其实在我们日常的编程中,对于缩放手势的使用并不是很经常,这一手势主要是用在图片浏览方面,比如下方例子.但是(敲重点),作为 Android 入门的基础来说,学习 ScaleGestureDetecto ...

  2. iOS火焰动画效果、图文混排框架、StackView效果、偏好设置、底部手势等源码

    iOS精选源码 高性能图文混排框架,构架顺滑的iOS应用. 使用OpenGLE覆盖阿尔法通道视频动画播放器视图. 可选最大日期截至当日日期的日期轮选器ChooseDatePicker 简单轻量的图片浏 ...

  3. 转盘抽奖 canvas & 抽奖 H5 源码

    转盘抽奖 canvas https://github.com/givebest/wechat-turntalbe-canvas https://blog.givebest.cn/GB-canvas-t ...

  4. android多框架实现短视频应用、3D手势旋转、banner控件、指南针、智能管家等应用源码

    Android精选源码 android智能管家app源码 Android高仿拼多多分类列表 Android百度地图实例详解之仿摩拜单车APP RecyclerView的LayoutManager搭建流 ...

  5. Android 手势识别类 ( 二 ) GestureDetector 源码浅析

    前言:Android 关于手势的操作提供两种形式:一种是针对用户手指在屏幕上划出的动作而进行移动的检测,这些手势的检测通过android提供的监听器来实现:另一种是用 户手指在屏幕上滑动而形成一定的不 ...

  6. ReentrantLock实现原理及源码分析

    ReentrantLock是Java并发包中提供的一个可重入的互斥锁.ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性.只不过相比原生的Sync ...

  7. Java读源码之ReentrantLock

    前言 ReentrantLock 可重入锁,应该是除了 synchronized 关键字外用的最多的线程同步手段了,虽然JVM维护者疯狂优化 synchronized 使其已经拥有了很好的性能.但 R ...

  8. html5 canvas简易版捕鱼达人游戏源码

    插件描述:html5利用canvas写的一个js版本的捕鱼,有积分统计,鱼可以全方位移动,炮会跟着鼠标移动,第一次打开需要鼠标移出背景图,再移入的时候就可以控制炮的转动,因为是用的mouseover触 ...

  9. WEB前端开发学习:源码canvas 雪

    WEB前端开发学习:源码canvas 雪 双旦节要到了,程序员们为了响应气氛,特别用代码制作了动态雪花,WEB前端开发学习的初学者们一起跟着案例做一遍吧! <!DOCTYPE html> ...

随机推荐

  1. [Python]获取win平台文件的详细信息

    import win32api def getFileProperties(fname): """ 读取给定文件的所有属性, 返回一个字典. ""&q ...

  2. Codeforces_793

    A.找最小的数,看每个数跟它的差是否被k整除. #include<bits/stdc++.h> #define MOD 1000000007 using namespace std; ] ...

  3. API 接口设计规范

    概述 这篇文章分享 API 接口设计规范,目的是提供给研发人员做参考. 规范是死的,人是活的,希望自己定的规范,不要被打脸. 路由命名规范 动作 前缀 备注 获取 get get{XXX} 获取 ge ...

  4. Golang定时任务简单实现

    下载cron包: go get github.com/robfig/cron 开启一个定时: 根据cron表达式进行时间调度,cron可以精确到秒,大部分表达式格式也是从秒开始. c := cron. ...

  5. c++ 中变量成员的初始化时机

    代码如下: 注意一下我打断点的位置. 最后的结果: 在程序进入MyTest()的函数体之前,控制台就打印出来了I have been constructed. 即:在进入构造函数的函数体之前,类中的成 ...

  6. 动手学习Pytorch(4)--过拟合欠拟合及其解决方案

    过拟合.欠拟合及其解决方案 过拟合.欠拟合的概念 权重衰减 丢弃法   模型选择.过拟合和欠拟合 训练误差和泛化误差 在解释上述现象之前,我们需要区分训练误差(training error)和泛化误差 ...

  7. vue的组件传值

    1.父组件向子组件传值 父组件: 123456789101112 <template> <child :name="name"></child> ...

  8. qt creator源码全方面分析(2-8)

    目录 Editing MIME Types Editing MIME Types Qt Creator使用文件的MIME类型,来确定用于打开文件的模式和编辑器. 例如,Qt Creator在C++编辑 ...

  9. 《算法导论》第二章demo代码实现(Java版)

    <算法导论>第二章demo代码实现(Java版) 前言 表示晚上心里有些不宁静,所以就写一篇博客,来缓缓.囧 拜读<算法导论>这样的神作,当然要做一些练习啦.除了练习题与思考题 ...

  10. 编程语言的实现,从AST(抽象语法树)开始

    学习博客:https://baijiahao.baidu.com/s?id=1626159656211187310&wfr=spider&for=pc