<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>手机解锁</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
<style>
body{
text-align: center;
background: #305066;
}
h4{
color: #22c3aa;
}
</style>
</head>
<body>
<script type="text/javascript" src="js/index.js"></script>
<script>
//1.生成背景
//2.动态title生成
//3.用js动态生成canvas标签
//4.js动态生成h3标签和canvas标签
new canvasLock({chooseType:3}).init(); </script>
</body>
</html>
(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 = '#cfe6ef';
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(){ //创建点的坐标,根据c
var n = this.chooseType; //n是指有几行圆
var count = 0;
this.r = this.ctx.canvas.width / (2+4*n);
//圆心坐标
this.lastPoint = [];
this.arr = []; //9个圆的中心点坐标
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);
}
} //程序初始化
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; //一个是canvas对象,一个是window.canvasLock对象
console.log(this); //如果直接使用this,那么this指向的就是当前时间调用的对象,也就是this.canvas,
console.log(self); //但是在代码中想要使用的是window.canvasLock对象,所以在事件外面提前将this赋值给self变量,确保this的指向问题。
this.canvas.addEventListener('touchstart',function(e){
//2.touchstart判断是否点击的位置处于园内getPosition,处于则初始化lastpoint、restPoint
var po = self.getPosition(e);
//判断是否在圆内的原理:多出来的这条 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;
self.lastPoint.push(self.arr[i]); //把点击的圆心的x轴y轴坐标放入lastPoint数组
console.log(self.lastPoint);
self.restPoint.splice(i,1);
break;
}
} },false);
this.canvas.addEventListener('touchmove',function(e){
// 3.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
//获取canvas上下左右离屏幕的距离
var rect = e.currentTarget.getBoundingClientRect(); // Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。
//po有x和y,并且使相较于canvas边距
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); //画完一个圆就将该圆从restPoint数组中去掉
break;
}
}
}
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 = '#cfe6fe';
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();
}
} 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. canvas一周一练 -- canvas绘制马尾图案 (5)

    运行效果: <!DOCTYPE html> <html> <head> </head> <body> <canvas id=" ...

  2. 粒子系统(二):Canvas绘制精美图案

    准备 IDE:Visual Studio Code Language:JavaScript / ECMAScript 6+ GitHub:Natural2D.JS 本文主要讲述 Particles - ...

  3. canvas 实现手机图案解锁

    参考☞: https://www.cnblogs.com/chenyingying0/ 先上效果图: 我是在 vue 里面实现js 文件 ,所以如果需要在vue 里面使用 可以将以下内容import  ...

  4. canvas手势解锁源码

    先放图 demo.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  5. 小程序利用canvas 绘制图案 (生成海报, 生成有特色的头像)

    小程序利用canvas 绘制图案 (生成海报, 生成有特色的头像) 微信小程序生成特色头像,海报等是比较常见的.下面我来介绍下实现该类小程序的过程. 首先选择前端来通过 canvas 绘制.这样比较节 ...

  6. 应用canvas绘制动态时钟--每秒自动动态更新时间

    使用canvas绘制时钟 下文是部分代码,完整代码参照:https://github.com/lemoncool/canvas-clock,可直接下载. 首先看一下效果图:每隔一秒会动态更新时间 一. ...

  7. canvas 绘制图形

    canvas 绘制图形: 注意: canvas 的宽高设置在行内,否则会使画布(canvas)产生扭曲,绘图变形: <!DOCTYPE html> <html lang=" ...

  8. html5--5-14 阶段小练习:绘制太极图案

    html5--5-14 阶段小练习:绘制太极图案 学习要点 运用前几节课的知识完成一个小练习 这个图案有多种不同的绘制方法,这里只做一个简单的演示,练习的时候可以自己思考一下,尝试其他的方法,或者对这 ...

  9. HTML5学习总结——canvas绘制象棋(canvas绘图)

    一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...

随机推荐

  1. 基于 apache-arrow 的 duckdb rust 客户端

    背景 duckdb 是一个 C++ 编写的单机版嵌入式分析型数据库.它刚开源的时候是对标 SQLite 的列存数据库,并提供与 SQLite 一样的易用性,编译成一个头文件和一个 cpp 文件就可以在 ...

  2. 【游记】OI 2020-2021(在更)

    [CSP-S2020初赛] [CSP-S2020] [NOIp 2020] [NOI冬令营 2021] [省选 2021] [NOI 2021]

  3. spring第三章

    第三章 实现AOP AOP:面向方面编程,AOP能够使您将所有模块共有的特性与应用程序的主要业务逻辑隔离开 一.AOP介绍 横切关注点:在Web应用程序中,有一些服务(如登录.安全和事务管理)不是应用 ...

  4. ajax()返回Array

    后台查询的数据为数组$arr,需要将数组 echo json_encode($arr);前台ajax拿到数据 然后用 eval("(+data+)"); 来将json转为json对 ...

  5. Spring Boot中使用时序数据库InfluxDB

    除了最常用的关系数据库和缓存之外,之前我们已经介绍了在Spring Boot中如何配置和使用MongoDB.LDAP这些存储的案例.接下来,我们继续介绍另一种特殊的数据库:时序数据库InfluxDB在 ...

  6. 王者并发课-钻石2:分而治之-如何从原理深入理解ForkJoinPool的快与慢

    欢迎来到<王者并发课>,本文是该系列文章中的第25篇,砖石中的第2篇. 在上一篇文章中,我们学习了线程池ThreadPoolExecutor,它通过对任务队列和线程的有效管理实现了对并发任 ...

  7. 剑指 Offer 40. 最小的k个数

    剑指 Offer 40. 最小的k个数 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:ar ...

  8. 接口管理效率神器Apifox

    前言 你是一个测试,你们团队目前开发模式是前后端分离. 某一天,版本V1.0接口评审完,发布在了swagger上,前后端各自进行开发.此时你根据接口文档将新接口迁移到JMeter上,然后开始编写接口测 ...

  9. Android源码解析——Handler、Looper与MessageQueue

    本文的目的是来分析下 Android 系统中以 Handler.Looper.MessageQueue 组成的异步消息处理机制,通过源码来了解整个消息处理流程的走向以及相关三者之间的关系 需要先了解以 ...

  10. 【NLP学习其五】模型保存与载入的注意事项(记问题No module named 'model')

    这是一次由于路径问题(找不到模型)引出模型保存问题的记录 最近,我试着把使用GPU训练完成的模型部署至预发布环境时出现了一个错误,以下是log节选 unpickler.load() ModuleNot ...