canvas手势解锁源码
先放图
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手势解锁源码的更多相关文章
- 缩放手势 ScaleGestureDetector 源码解析,这一篇就够了
其实在我们日常的编程中,对于缩放手势的使用并不是很经常,这一手势主要是用在图片浏览方面,比如下方例子.但是(敲重点),作为 Android 入门的基础来说,学习 ScaleGestureDetecto ...
- iOS火焰动画效果、图文混排框架、StackView效果、偏好设置、底部手势等源码
iOS精选源码 高性能图文混排框架,构架顺滑的iOS应用. 使用OpenGLE覆盖阿尔法通道视频动画播放器视图. 可选最大日期截至当日日期的日期轮选器ChooseDatePicker 简单轻量的图片浏 ...
- 转盘抽奖 canvas & 抽奖 H5 源码
转盘抽奖 canvas https://github.com/givebest/wechat-turntalbe-canvas https://blog.givebest.cn/GB-canvas-t ...
- android多框架实现短视频应用、3D手势旋转、banner控件、指南针、智能管家等应用源码
Android精选源码 android智能管家app源码 Android高仿拼多多分类列表 Android百度地图实例详解之仿摩拜单车APP RecyclerView的LayoutManager搭建流 ...
- Android 手势识别类 ( 二 ) GestureDetector 源码浅析
前言:Android 关于手势的操作提供两种形式:一种是针对用户手指在屏幕上划出的动作而进行移动的检测,这些手势的检测通过android提供的监听器来实现:另一种是用 户手指在屏幕上滑动而形成一定的不 ...
- ReentrantLock实现原理及源码分析
ReentrantLock是Java并发包中提供的一个可重入的互斥锁.ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性.只不过相比原生的Sync ...
- Java读源码之ReentrantLock
前言 ReentrantLock 可重入锁,应该是除了 synchronized 关键字外用的最多的线程同步手段了,虽然JVM维护者疯狂优化 synchronized 使其已经拥有了很好的性能.但 R ...
- html5 canvas简易版捕鱼达人游戏源码
插件描述:html5利用canvas写的一个js版本的捕鱼,有积分统计,鱼可以全方位移动,炮会跟着鼠标移动,第一次打开需要鼠标移出背景图,再移入的时候就可以控制炮的转动,因为是用的mouseover触 ...
- WEB前端开发学习:源码canvas 雪
WEB前端开发学习:源码canvas 雪 双旦节要到了,程序员们为了响应气氛,特别用代码制作了动态雪花,WEB前端开发学习的初学者们一起跟着案例做一遍吧! <!DOCTYPE html> ...
随机推荐
- CCF_201312-1_出现次数最多的数
水. #include<stdio.h> int main() { ,a[]={},num[]={}; scanf("%d",&T); ;i < T;i+ ...
- 源码详解系列(八) ------ 全面讲解HikariCP的使用和源码
简介 HikariCP 是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能,另外,和 dr ...
- UNIX读书笔记----UNIX基础知识
UNIX体系结构: 从严格意义上讲,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.我们通常将这种软件称为内核(Kernel),因为他相对较小,而且位于环境的核心.图片显示了UNI ...
- 查看php相关信息
1.最常见的就是 创建一个 php页面 ,例如 test.php, 内容如下 <?php phpinfo();?> 直接访问 这个页面,就可以看到php的 信息了 2.其它方法 直 ...
- Cobalt Strike Bypassing Windows Defender 使用混淆处理
Cobalt Strike – Bypassing Windows Defender 混淆处理 对于所有红色团队成员来说,在交付有效的替代品同时又不拖延延展组织的所有风吹草动始终是一个挑战.就像所有其 ...
- React之JSX的语法细节
带注释 import React, { Component, Fragment } from 'react' import './style.css' class TodoList extends C ...
- VueJs一步步实现带感的帮助面板
环境 IDE: WebStorm 2019.1.4 系统: Mac OS X 10.15.4 VueJs: 2.6.11 Vue-cli: 4.2.2 前言 最近一直在忙毕设,前端终于还是对我这个 ...
- spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- Uncaught TypeError: Cannot set property 'onclick' of null解决办法
如果把js内容直接放在这个head标签以内,button按钮不能正常点击更换body的背景颜色,报错提示:demo6.html:16 Uncaught TypeError: Cannot set pr ...
- AndroidStudio报错:Could not download gradle.jar:No cacahed version available for offline mode
场景 在讲Android Studio 的.gradle目录从默认C盘修改为 别的目录后,新建app提示: Could not download gradle.jar:No cacahed versi ...