手势解锁,HTML5实现屏幕手势解锁

日期:2019-09-16编辑作者:澳门金莎娱乐网站

HTML5贯彻显示器手势解锁

2015/07/18 · HTML5 · 1 评论 · 手势解锁

原著出处: AlloyTeam   

成效展现

澳门金莎娱乐网站 1

贯彻原理 利用HTML5的canvas,将解锁的范围划出,利用touch事件解锁那几个层面,直接看代码。

JavaScript

function createCircle() {// 创设解锁点的坐标,根据canvas的轻重来平均分配半径 var n = chooseType;// 画出n*n的矩阵 lastPoint = []; arr = []; restPoint = []; r = ctx.canvas.width / (2 + 4 * n);// 公式总计 半径和canvas的轻重有关 for (var i = 0 ; i < n ; i++) { for (var j = 0 ; j < n ; j++) { arr.push({ x: j * 4 * r + 3 * r, y: i * 4 * r + 3 * r }); restPoint.push({ x: j * 4 * r + 3 * r, y: i * 4 * r + 3 * r }); } } //return arr; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function createCircle() {// 创建解锁点的坐标,根据canvas的大小来平均分配半径
 
        var n = chooseType;// 画出n*n的矩阵
        lastPoint = [];
        arr = [];
        restPoint = [];
        r = ctx.canvas.width / (2 + 4 * n);// 公式计算 半径和canvas的大小有关
        for (var i = 0 ; i < n ; i++) {
            for (var j = 0 ; j < n ; j++) {
                arr.push({
                    x: j * 4 * r + 3 * r,
                    y: i * 4 * r + 3 * r
                });
                restPoint.push({
                    x: j * 4 * r + 3 * r,
                    y: i * 4 * r + 3 * r
                });
            }
        }
        //return arr;
    }

canvas里的圆形画好之后方可实行事件绑定

JavaScript

function bindEvent() { can.addEventListener("touchstart", function (e) { var po = getPosition(e); console.log(po); for (var i = 0 ; i < arr.length ; i++) { if (Math.abs(po.x - arr[i].x) < r && Math.abs(po.y - arr[i].y) < r) { // 用来剖断初始点是不是在规模内部 touchFlag = true; drawPoint(arr[i].x,arr[i].y); lastPoint.push(arr[i]); restPoint.splice(i,1); break; } } }, false); can.addEventListener("touchmove", function (e) { if (touchFlag) { update(getPosition(e)); } }, false); can.addEventListener("touchend", function (e) { if (touchFlag) { touchFlag = false; storePass(lastPoint); setTimeout(function(){ init(); }, 300); } }, false); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function bindEvent() {
        can.addEventListener("touchstart", function (e) {
             var po = getPosition(e);
             console.log(po);
             for (var i = 0 ; i < arr.length ; i++) {
                if (Math.abs(po.x - arr[i].x) < r && Math.abs(po.y - arr[i].y) < r) { // 用来判断起始点是否在圈圈内部
 
                    touchFlag = true;
                    drawPoint(arr[i].x,arr[i].y);
                    lastPoint.push(arr[i]);
                    restPoint.splice(i,1);
                    break;
                }
             }
         }, false);
         can.addEventListener("touchmove", function (e) {
            if (touchFlag) {
                update(getPosition(e));
            }
         }, false);
         can.addEventListener("touchend", function (e) {
             if (touchFlag) {
                 touchFlag = false;
                 storePass(lastPoint);
                 setTimeout(function(){
 
                    init();
                }, 300);
             }
 
         }, false);
    }

随即到了最要害的手续绘制解锁路线逻辑,通过touchmove事件的不停触发,调用canvas的moveTo方法和lineTo方法来画出折现,同有时等候法庭判果决是或不是达到规定的规范大家所画的范畴里面,在那之中lastPoint保存不易的框框路线,restPoint保存全体局面去除正确路子之后剩余的。 Update方法:

JavaScript

function update(po) {// 大旨转移情势在touchmove时候调用 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); for (var i = 0 ; i < arr.length ; i++) { // 每帧先把面板画出来 drawCle(arr[i].x, arr[i].y); } drawPoint(lastPoint);// 每帧花轨迹 drawLine(po , lastPoint);// 每帧画圆心 for (var i = 0 ; i < restPoint.length ; i++) { if (Math.abs(po.x - restPoint[i].x) < r && Math.abs(po.y - restPoint[i].y) < r) { drawPoint(restPoint[i].x, restPoint[i].y); lastPoint.push(restPoint[i]); restPoint.splice(i, 1); break; } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function update(po) {// 核心变换方法在touchmove时候调用
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
 
        for (var i = 0 ; i < arr.length ; i++) { // 每帧先把面板画出来
            drawCle(arr[i].x, arr[i].y);
        }
 
        drawPoint(lastPoint);// 每帧花轨迹
        drawLine(po , lastPoint);// 每帧画圆心
 
        for (var i = 0 ; i < restPoint.length ; i++) {
            if (Math.abs(po.x - restPoint[i].x) < r && Math.abs(po.y - restPoint[i].y) < r) {
                drawPoint(restPoint[i].x, restPoint[i].y);
                lastPoint.push(restPoint[i]);
                restPoint.splice(i, 1);
                break;
            }
        }
 
    }

终极就是甘休职业,把门路里面包车型地铁lastPoint保存的数组产生密码存在localstorage里面,之后就用来处通晓锁验证逻辑了

JavaScript

function storePass(psw) {// touchend结束未来对密码和气象的处理 if (pswObj.step == 1) { if (checkPass(pswObj.fpassword, psw)) { pswObj.step = 2; pswObj.spassword = psw; document.getElementById('title').innerHTML = '密码保存成功'; drawStatusPoint('#2CFF26'); window.localStorage.setItem('passwordx', JSON.stringify(pswObj.spassword)); window.localStorage.setItem('chooseType', chooseType); } else { document.getElementById('title').innerHTML = '一回不平等,重新输入'; drawStatusPoint('red'); delete pswObj.step; } } else if (pswObj.step == 2) { if (checkPass(pswObj.spassword, psw)) { document.getElementById('title').innerHTML = '解锁成功'; drawStatusPoint('#2CFF26'); } else { drawStatusPoint('red'); document.getElementById('title').innerHTML = '解锁失败'; } } else { pswObj.step = 1; pswObj.fpassword = psw; document.getElementById('title').innerHTML = '再度输入'; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function storePass(psw) {// touchend结束之后对密码和状态的处理
        if (pswObj.step == 1) {
            if (checkPass(pswObj.fpassword, psw)) {
                pswObj.step = 2;
                pswObj.spassword = psw;
                document.getElementById('title').innerHTML = '密码保存成功';
                drawStatusPoint('#2CFF26');
                window.localStorage.setItem('passwordx', JSON.stringify(pswObj.spassword));
                window.localStorage.setItem('chooseType', chooseType);
            } else {
                document.getElementById('title').innerHTML = '两次不一致,重新输入';
                drawStatusPoint('red');
                delete pswObj.step;
            }
        } else if (pswObj.step == 2) {
            if (checkPass(pswObj.spassword, psw)) {
                document.getElementById('title').innerHTML = '解锁成功';
                drawStatusPoint('#2CFF26');
            } else {
                drawStatusPoint('red');
                document.getElementById('title').innerHTML = '解锁失败';
            }
        } else {
            pswObj.step = 1;
            pswObj.fpassword = psw;
            document.getElementById('title').innerHTML = '再次输入';
        }
 
    }

解锁组件

将这一个HTML5解锁写成了一个组件,放在

二维码体验: 澳门金莎娱乐网站 2

 

参考资料:

1 赞 4 收藏 1 评论

澳门金莎娱乐网站 3

澳门金莎娱乐网站 4

用 canvas 实现 Web 手势解锁

2017/04/04 · HTML5 · Canvas

原稿出处: songjz   

前不久参预 360 暑假的前端星布置,有三个在线作业,甘休日期是 3 月 30 号,让手动完成一个 H5 手势解锁,具体的机能就好像原新手提式有线电话机的九宫格解锁那样。

澳门金莎娱乐网站 5

落到实处的最后效果就疑似上面那张图那样:

澳门金莎娱乐网站 6

宗旨要求是如此的:将密码保存到 localStorage 里,伊始的时候会从本土读取密码,若无就让客商安装密码,密码最少为陆人数,少于两人要提醒错误。须求对第一遍输入的密码实行认证,四回同样技巧维系,然后是表明密码,能够对客商输入的密码举行求证。

直白想用HTML5做个小游戏,但接二连三未有的时候间,前几日抽了多少个钟头做了个打地鼠的小游戏,体验一下HTML5上的游玩开拓。本着OSC的共享精神,特分享出来。没有花时间去找越来越多的材质,再加上本来就稍微会做图,出了要命地洞的资料以外其余的全都以从互连网搜到的。代码也比较混乱,大家就凑合着看看啊,迎接大家商量指正,也接待大家能把这几个小游戏做的更完善些。

金玉锦绣原理应用HTML5的canvas,将解锁的范围划出,利用touch事件解锁这么些层面,直接看代码。

H5 手势解锁

扫码在线查看:

澳门金莎娱乐网站 7

可能点击查看手机版。

项目 GitHub 地址,H5HandLock。

首先,笔者要证实一下,对于这几个类型,作者是参照外人的,H5lock。

自己感到贰个相比客观的解法应该是采用 canvas 来落到实处,不精通有未有大神用 css 来完毕。假设纯用 css 的话,能够将连线先安装 display: none,当手指划过的时候,显示出来。光设置那个本该就不行麻烦呢。

事先明白过 canvas,但不曾真的的写过,上面就来介绍自个儿近期学习 canvas 并贯彻 H5 手势解锁的历程。

废话不说了,大家先看看效果啊:

functioncreateCircle(){// 创设解锁点的坐标,根据canvas的分寸来平均分配半径

预备及布局设置

自家那边用了贰个相比正规的做法:

(function(w){ var handLock = function(option){} handLock.prototype = { init : function(){}, ... } w.handLock = handLock; })(window) // 使用 new handLock({ el: document.getElementById('id'), ... }).init();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function(w){
  var handLock = function(option){}
 
  handLock.prototype = {
    init : function(){},
    ...
  }
 
  w.handLock = handLock;
})(window)
 
// 使用
new handLock({
  el: document.getElementById('id'),
  ...
}).init();

健康办法,比较易懂和操作,缺欠正是,能够被任意的退换。

传播的参数中要含有二个 dom 对象,会在那个 dom 对象內创设一个canvas。当然还恐怕有局地任何的 dom 参数,比方 message,info 等。

至于 css 的话,懒得去新建文件了,就径直內联了。

澳门金莎娱乐网站 8

varn = chooseType;// 画出n*n的矩阵

canvas

HTML文件:  

lastPoint = [];

1. 上学 canvas 并消除画圆

MDN 上面有个大约的教程,大约浏览了一下,感觉还能够。Canvas教程。

先创制三个 canvas,然后设置其大小,并通过 getContext 方法赢得壁画的上下文:

var canvas = document.createElement('canvas'); canvas.width = canvas.height = width; this.el.appendChild(canvas); this.ctx = canvas.getContext('2d');

1
2
3
4
5
var canvas = document.createElement('canvas');
canvas.width = canvas.height = width;
this.el.appendChild(canvas);
 
this.ctx = canvas.getContext('2d');

然后呢,先画 n*n 个圆出来:

JavaScript

createCircles: function(){ var ctx = this.ctx, drawCircle = this.drawCircle, n = this.n; this.r = ctx.canvas.width / (2 + 4 * n) // 这里是参谋的,认为这种画圆的不二秘诀挺合理的,方方圆圆 r = this.r; this.circles = []; // 用来积存圆心的任务 for(var i = 0; i < n; i++){ for(var j = 0; j < n; j++){ var p = { x: j * 4 * r + 3 * r, y: i * 4 * r + 3 * r, id: i * 3 + j } this.circles.push(p); } } ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // 为了防卫重复画 this.circles.forEach(function(v){ drawCircle(ctx, v.x, v.y); // 画每种圆 }) }, drawCircle: function(ctx, x, y){ // 画圆函数 ctx.strokeStyle = '#FFFFFF'; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(x, y, this.r, 0, Math.PI * 2, true); ctx.closePath(); ctx.stroke(); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
createCircles: function(){
  var ctx = this.ctx,
    drawCircle = this.drawCircle,
    n = this.n;
  this.r = ctx.canvas.width / (2 + 4 * n) // 这里是参考的,感觉这种画圆的方式挺合理的,方方圆圆
  r = this.r;
  this.circles = []; // 用来存储圆心的位置
  for(var i = 0; i < n; i++){
    for(var j = 0; j < n; j++){
      var p = {
        x: j * 4 * r + 3 * r,
        y: i * 4 * r + 3 * r,
        id: i * 3 + j
      }
      this.circles.push(p);
    }
  }
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // 为了防止重复画
  this.circles.forEach(function(v){
    drawCircle(ctx, v.x, v.y); // 画每个圆
  })
},
 
drawCircle: function(ctx, x, y){ // 画圆函数
  ctx.strokeStyle = '#FFFFFF';
  ctx.lineWidth = 2;
  ctx.beginPath();
  ctx.arc(x, y, this.r, 0, Math.PI * 2, true);
  ctx.closePath();
  ctx.stroke();
}

画圆函数,须要静心:怎么着规定圆的半径和各类圆的圆心坐标(那些本身是参照他事他说加以考察的),若是以圆心为宗旨,种种圆上下左右各扩充叁个半径的偏离,同期为了避防万一四边太挤,四周在填写叁个半径的相距。那么获得的半径就是 width / ( 4 * n + 2),对应也足以算出各样圆所在的圆心坐标,也可能有一套公式,GET

01     <!DOCTYPE html>
02     <html lang="en" >
03         <head>
04             <meta charset="utf-8" />
05             <title>打地鼠</title>
06             <script type="text/javascript" src="js/game.js"></script>
07         </head>
08         <body onload="init()">
09             <div class="container">
10                 <canvas onmouseover="hideCursor(this)" onmouseout="showCursor"
11                         onmousemove="hammerMove(this);"
12                         onmousedown="hammerDown();" onmouseUp="hammerUp();"
13                         id="screen" width="700" height="500" style="border:1px solid #000"></canvas>
14             </div>
15            
16             <div id="info"></div>
17         </body>
18     </html>
 
 
 
JS文件:
 
 
001  var canvas, ctx, info;
002  var bg;
003  var hammer, hamX, hamY;
004  var mouseState, mouseFrmLen = 10, mousePress = false;
005  var sprites = [], holes = [];
006  var score = 0;
007  var Sprite = function(w, h, x, y, state, image){
008      var self = this;
009      this.w = w;
010      this.h = h;
011      this.x = x;
012      this.y = y;
013      this.image = image;
014      this.state = state;
015     
016      this.draw = function(){
017          if(this.state == 'show'){
018              ctx.drawImage(this.image, this.x, this.y, this.w, this.h);
019              setTimeout(function(){
020                  self.state = 'hide';
021              },3000);
022          }
023      }
024  }
025 
026  var HoleSprite = function(w, h, x, y, state, image){
027      var self = this;
028      this.w = w;
029      this.h = h;
030      this.x = x;
031      this.y = y;
032      this.image = image;
033      this.state = state;
034     
035      this.draw = function(){
036          if(this.state == 'show'){
037              ctx.drawImage(this.image, this.x, this.y, this.w, this.h);
038          }
039      }
040  }
041 
042  function HammerSprite(w, h, x, y, image){
043      HammerSprite.prototype.w = w;
044      HammerSprite.prototype.h = h;
045      HammerSprite.prototype.x = x;
046      HammerSprite.prototype.y = y;
047     
048      HammerSprite.prototype.draw = function(isPress){
049          if(isPress){
050              ctx.save();
051             
052              ctx.translate(this.x-10, this.y+34);
053              ctx.rotate(Math.PI/180*330);
054              ctx.drawImage(image, 0, 0, w, h);
055             
056              ctx.restore();
057          }else{
058              ctx.drawImage(image, this.x, this.y, w, h);
059          }
060         
061      }
062  }
063 
澳门金莎娱乐网站,064  function clearScreen(){
065      //ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
066      ctx.drawImage(bg, 0, 0, ctx.canvas.width, ctx.canvas.height);
067  }
068 
069  function drawScreen(){
070      clearScreen();
071     
072      //绘制得分
073     
074      ctx.font = "40px serif"
075      ctx.strokeStyle = "#FF00ff";
076      ctx.strokeText ("LION打地鼠", 50,50);
077      ctx.fillStyle = "#000000";
078      ctx.fillText("LION打地鼠",50,50);
079 
080      ctx.fillStyle = "#ff0000";
081      ctx.fillText("你的得分:"+score,450,50);
082      for(i=0;i<3;i++){
083          for(j=0; j<3; j++){
084              holes[i][j].draw();
085          }
086      }
087     
088 
089      for(i=0;i<3;i++){
090          for(j=0; j<3; j++){
091              sprites[i][j].draw();
092          }
093      }
094     
095      if(hammer){
096          hammer.draw(mousePress);
097      }
098  }
099 
100  function updateLogic(){
101 
102      for(i=0;i<3;i++){
103          for(j=0; j<3; j++){
104              sprites[i][j].state=='hide'
105          }
106      }
107     
108      var a = Math.round(Math.random()*100)%3;
109      var b = Math.round(Math.random()*100)%3;
110      sprites[a][b].state='show';
111  }
112 
113 
114  function hammerMove(e){
115      if(hammer){
116          hammer.x = event.x-40;
117          hammer.y = event.y-40;
118      }
119  }
120 
121  function hit(x, y){
122     
123      for(i=0;i<3;i++){
124          for(j=0;j<3;j++){
125              var s = sprites[i][j];
126             
127              if(s.state=='show'){
128                  if(x>s.x+30 && y>s.y && x<(s.x+s.w+30) && y<(s.y+s.h)){
129                      score++;
130                      s.state = 'hide';
131                  }
132              }
133          }
134      }
135  }
136 
137  function init(){
138      info = document.getElementById('info');
139      canvas = document.getElementById('screen');
140      ctx = canvas.getContext('2d');
141     
142      bg = new Image();
143      bg.src = 'bg.jpg';
144      bg.onload = function(){};
145     
146     
147      var hamImg = new Image();
148      hamImg.src = 'hammer.png';
149      hamImg.onload = function(){
150          hammer = new HammerSprite(48, 48, 100, 100, hamImg);
151      }
152     
153      var msImg = new Image();
154      msImg.src = 'mouse.png';
155     
156      msImg.onload = function(){
157          for(i=0;i<3;i++){
158              var arr = [];
159              for(j=0; j<3; j++){
160                  var s = new Sprite(60, 70, 50+240*i, 80+120*j, 'hide', msImg);
161                  arr[j] = s;
162              }
163              sprites[i] = arr;
164          }     
165      }
166     
167      var holeImg = new Image();
168      holeImg.src = 'hole.png';
169      holeImg.onload = function(){
170          for(i=0;i<3;i++){
171              var arr = [];
172              for(j=0; j<3; j++){
173                  var s = new HoleSprite(80, 30, 40+240*i, 140+120*j, 'show', holeImg);
174                  arr[j] = s;
175              }
176              holes[i] = arr;
177          }     
178      }
179     
180      setInterval(drawScreen, 30);
181      setInterval(updateLogic, 3000);
182     
183  };
184 
185  function hammerDown(){
186      mousePress = true;
187  }
188 
189  function hammerUp(){
190 
191      info.innerHTML=event.x+':'+event.y;
192      mousePress = false;
193      hit(event.x, event.y);
194  }
195 
196  function hideCursor(obj){
197      obj.style.cursor='none';
198  }
199 
200  function showCursor(obj){
201      obj.style.cursor='';
202  }    

arr = [];

2. 画线

画线须求借助 touch event 来产生,也正是,当我们 touchstart 的时候,传入开始时的相对坐标,作为线的一面,当大家 touchmove 的时候,得到坐标,作为线的另一面,当大家 touchend 的时候,起首画线。

那只是一个测量试验画线成效,具体的前面再扩充改换。

有八个函数,拿到当前 touch 的相对坐标:

getTouchPos: function(e){ // 得到触摸点的相对地方 var rect = e.target.getBoundingClientRect(); var p = { // 相对坐标 x: e.touches[0].clientX - rect.left, y: e.touches[0].clientY - rect.top }; return p; }

1
2
3
4
5
6
7
8
getTouchPos: function(e){ // 获得触摸点的相对位置
  var rect = e.target.getBoundingClientRect();
  var p = { // 相对坐标
    x: e.touches[0].clientX - rect.left,
    y: e.touches[0].clientY - rect.top
  };
  return p;
}

画线:

drawLine: function(p1, p2){ // 画线 this.ctx.beginPath(); this.ctx.lineWidth = 3; this.ctx.moveTo(p1.x, p2.y); this.ctx.lineTo(p.x, p.y); this.ctx.stroke(); this.ctx.closePath(); },

1
2
3
4
5
6
7
8
drawLine: function(p1, p2){ // 画线
  this.ctx.beginPath();
  this.ctx.lineWidth = 3;
  this.ctx.moveTo(p1.x, p2.y);
  this.ctx.lineTo(p.x, p.y);
  this.ctx.stroke();
  this.ctx.closePath();
},

接下来正是监听 canvas 的 touchstarttouchmove、和 touchend 事件了。

能源图形:

restPoint = [];

3. 画折线

所谓的画折线,就是,将已经触动到的点连起来,能够把它当作是画折线。

先是,要用五个数组,贰个数组用于已经 touch 过的点,另三个数组用于存款和储蓄未 touch 的点,然后在 move 监听时候,对 touch 的绝对地点举行判别,假若触到点,就把该点从未 touch 移到 touch 中,然后,画折线,思路也很简短。

JavaScript

drawLine: function(p){ // 画折线 this.ctx.beginPath(); this.ctx.lineWidth = 3; this.ctx.moveTo(this.touchCircles[0].x, this.touchCircles[0].y); for (var i = 1 ; i < this.touchCircles.length ; i++) { this.ctx.lineTo(this.touchCircles[i].x, this.touchCircles[i].y); } this.ctx.lineTo(p.x, p.y); this.ctx.stroke(); this.ctx.closePath(); },

1
2
3
4
5
6
7
8
9
10
11
drawLine: function(p){ // 画折线
  this.ctx.beginPath();
  this.ctx.lineWidth = 3;
  this.ctx.moveTo(this.touchCircles[0].x, this.touchCircles[0].y);
  for (var i = 1 ; i < this.touchCircles.length ; i++) {
    this.ctx.lineTo(this.touchCircles[i].x, this.touchCircles[i].y);
  }
  this.ctx.lineTo(p.x, p.y);
  this.ctx.stroke();
  this.ctx.closePath();
},

JavaScript

judgePos: function(p){ // 判断 触点 是否在 circle 內 for(var i = 0; i < this.restCircles.length; i++){ temp = this.restCircles[i]; if(Math.abs(p.x - temp.x) < r && Math.abs(p.y - temp.y) < r){ this.touchCircles.push(temp); this.restCircles.splice(i, 1); this.touchFlag = true; break; } } }

1
2
3
4
5
6
7
8
9
10
11
judgePos: function(p){ // 判断 触点 是否在 circle 內
  for(var i = 0; i < this.restCircles.length; i++){
    temp = this.restCircles[i];
    if(Math.abs(p.x - temp.x) < r && Math.abs(p.y - temp.y) < r){
      this.touchCircles.push(temp);
      this.restCircles.splice(i, 1);
      this.touchFlag = true;
      break;
    }
  }
}

 

r = ctx.canvas.width / (2+4* n);// 公式总结 半径和canvas的大大小小有关

4. 符号已画

前边早就说了,大家把曾经 touch 的点(圆)放到数组中,那年需求将那几个早就 touch 的点给标识一下,在圆心处画一个小实心圆:

JavaScript

drawPoints: function(){ for (var i = 0 ; i < this.touchCircles.length ; i++) { this.ctx.fillStyle = '#FFFFFF'; this.ctx.beginPath(); this.ctx.arc(this.touchCircles[i].x, this.touchCircles[i].y, this.r / 2, 0, Math.PI * 2, true); this.ctx.closePath(); this.ctx.fill(); } }

1
2
3
4
5
6
7
8
9
drawPoints: function(){
  for (var i = 0 ; i < this.touchCircles.length ; i++) {
    this.ctx.fillStyle = '#FFFFFF';
    this.ctx.beginPath();
    this.ctx.arc(this.touchCircles[i].x, this.touchCircles[i].y, this.r / 2, 0, Math.PI * 2, true);
    this.ctx.closePath();
    this.ctx.fill();
  }
}

同不常候加上二个 reset 函数,当 touchend 的时候调用,400ms 调用 reset 复位canvas。

到现行反革命终结,贰个 H5 手势解锁的简易版已经基本达成。

澳门金莎娱乐网站 9

for(vari =0; i < n ; i++) {

password

为了要促成记住和复位密码的功用,把 password 保存在 localStorage 中,但首先要增加必要的 html 和体制。

澳门金莎娱乐网站 10澳门金莎娱乐网站 11澳门金莎娱乐网站 12

for(varj =0; j < n ; j++) {

1. 添加 message 和 单选框

为了尽量的使分界面简单(越丑越好),直接在 body 后边增加了:

XHTML

<div id="select"> <div class="message">请输出手势密码</div> <div class="radio"> <label><input type="radio" name="pass">设置手势密码</label> <label><input type="radio" name="pass">验证手势密码</label> </div> </div>

1
2
3
4
5
6
7
<div id="select">
  <div class="message">请输入手势密码</div>
  <div class="radio">
    <label><input type="radio" name="pass">设置手势密码</label>
    <label><input type="radio" name="pass">验证手势密码</label>
  </div>
</div>

将助长到 dom 已 option 的款式传给 handLock:

var el = document.getElementById('handlock'), info = el.getElementsByClassName('info')[0], select = document.getElementById('select'), message = select.getElementsByClassName('message')[0], radio = select.getElementsByClassName('radio')[0], setPass = radio.children[0].children[0], checkPass = radio.children[1].children[0]; new handLock({ el: el, info: info, message: message, setPass: setPass, checkPass: checkPass, n: 3 }).init();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var el = document.getElementById('handlock'),
  info = el.getElementsByClassName('info')[0],
  select = document.getElementById('select'),
  message = select.getElementsByClassName('message')[0],
  radio = select.getElementsByClassName('radio')[0],
  setPass = radio.children[0].children[0],
  checkPass = radio.children[1].children[0];
new handLock({
  el: el,
  info: info,
  message: message,
  setPass: setPass,
  checkPass: checkPass,
  n: 3
}).init();

作者 lion_yang

arr.push({

2. info 音信显示

至于 info 信息浮现,本身写了贰个悬浮窗,然后默以为 display: none,然后写了三个 showInfo 函数用来展现提醒音讯,直接调用:

showInfo: function(message, timer){ // 特意用来体现 info var info = this.dom.info; info.innerHTML = message; info.style.display = 'block'; setTimeout(function(){ info.style.display = ''; }, 一千) }

1
2
3
4
5
6
7
8
showInfo: function(message, timer){ // 专门用来显示 info
  var info = this.dom.info;
  info.innerHTML = message;
  info.style.display = 'block';
  setTimeout(function(){
    info.style.display = '';
  }, 1000)
}

关于 info 的样式,在 html 中呢。

...

x: j *4* r +3* r,

3. 有关密码

先不考虑从 localStorage 读取四情形,新加三个 lsPass 对象,特意用于存款和储蓄密码,由于密码情状很多,比方设置密码,三遍确认密码,验证密码,为了方便管理,近些日子设置了密码的三种方式,分别是:

model:1 表达密码格局

model:2 安装密码情势

model:3 设置密码三遍验证

切切实实看下边这几个图:

澳门金莎娱乐网站 13

那二种 model ,只要管理好它们中间如何跳转就 ok 了,即状态的改动。

据此就有了 initPass:

initPass: function(){ // 将密码起首化 this.lsPass = w.localStorage.getItem('HandLockPass') ? { model: 1, pass: w.localStorage.getItem('HandLockPass').split('-') } : { model: 2 }; this.updateMessage(); }, updateMessage: function(){ // 依照前段时间方式,更新 dom if(this.lsPass.model == 2){ this.dom.setPass.checked = true; this.dom.message.innerHTML = '请设置手势密码'; }else if(this.lsPass.model == 1){ this.dom.checkPass.checked = true; this.dom.message.innerHTML = '请证实手势密码'; }else if(this.lsPass.model = 3){ this.dom.setPass.checked = true; this.dom.message.innerHTML = '请再次输入密码'; } },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
initPass: function(){ // 将密码初始化
  this.lsPass = w.localStorage.getItem('HandLockPass') ? {
    model: 1,
    pass: w.localStorage.getItem('HandLockPass').split('-')
  } : { model: 2 };
  this.updateMessage();
},
 
updateMessage: function(){ // 根据当前模式,更新 dom
  if(this.lsPass.model == 2){
    this.dom.setPass.checked = true;
    this.dom.message.innerHTML = '请设置手势密码';
  }else if(this.lsPass.model == 1){
    this.dom.checkPass.checked = true;
    this.dom.message.innerHTML = '请验证手势密码';
  }else if(this.lsPass.model = 3){
    this.dom.setPass.checked = true;
    this.dom.message.innerHTML = '请再次输入密码';
  }
},

有不能缺少再来介绍一下 lsPass 的格式:

this.lsPass = { model:1, // 代表如今的情势 pass: [0, 1, 2, 4, 5] // 表示近日的密码,大概不设有 }

1
2
3
4
this.lsPass = {
  model:1, // 表示当前的模式
  pass: [0, 1, 2, 4, 5] // 表示当前的密码,可能不存在
}

因为前面早就有了一个为主的落到实处框架,今后只必要在 touchend 之后,写一个函数,成效正是先对近来的 model 进行判别,达成对应的功能,这里要用到 touchCircles 数组,表示密码的相继:

JavaScript

checkPass: function(){ var succ, model = this.lsPass.model; //succ 今后会用到 if(model == 2){ // 设置密码 if(this.touchCircles.length < 5){ // 验证密码长度 succ = false; this.showInfo('密码长度至少为 5!', 一千); }else{ succ = true; this.lsPass.temp = []; // 将密码放到不时区存款和储蓄 for(var i = 0; i < this.touchCircles.length; i++){ this.lsPass.temp.push(this.touchCircles[i].id); } this.lsPass.model = 3; this.showInfo('请再度输入密码', 1000); this.updateMessage(); } }else if(model == 3){// 确认密码 var flag = true; // 先要验证密码是或不是科学 if(this.touchCircles.length == this.lsPass.temp.length){ var tc = this.touchCircles, lt = this.lsPass.temp; for(var i = 0; i < tc.length; i++){ if(tc[i].id != lt[i]){ flag = false; } } }else{ flag = false; } if(!flag){ succ = false; this.showInfo('四回密码不雷同,请重新输入', 一千); this.lsPass.model = 2; // 由于密码不得法,重新回来 model 2 this.updateMessage(); }else{ succ = true; // 密码准确,localStorage 存款和储蓄,并安装情形为 model 1 w.localStorage.setItem('HandLockPass', this.lsPass.temp.join('-')); // 存储字符串 this.lsPass.model = 1; this.lsPass.pass = this.lsPass.temp; this.updateMessage(); } delete this.lsPass.temp; // 很要紧,必须求删掉,bug }else if(model == 1){ // 验证密码 var tc = this.touchCircles, lp = this.lsPass.pass, flag = true; if(tc.length == lp.length){ for(var i = 0; i < tc.length; i++){ if(tc[i].id != lp[i]){ flag = false; } } }else{ flag = false; } if(!flag){ succ = false; this.showInfo('很不满,密码错误', 1000); }else{ succ = true; this.showInfo('恭喜你,验证通过', 一千); } } },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
checkPass: function(){
  var succ, model = this.lsPass.model; //succ 以后会用到
  if(model == 2){ // 设置密码
    if(this.touchCircles.length < 5){ // 验证密码长度
      succ = false;
      this.showInfo('密码长度至少为 5!', 1000);
    }else{
      succ = true;
      this.lsPass.temp = []; // 将密码放到临时区存储
      for(var i = 0; i < this.touchCircles.length; i++){
        this.lsPass.temp.push(this.touchCircles[i].id);
      }
      this.lsPass.model = 3;
      this.showInfo('请再次输入密码', 1000);
      this.updateMessage();
    }
  }else if(model == 3){// 确认密码
    var flag = true;
    // 先要验证密码是否正确
    if(this.touchCircles.length == this.lsPass.temp.length){
      var tc = this.touchCircles, lt = this.lsPass.temp;
      for(var i = 0; i < tc.length; i++){
        if(tc[i].id != lt[i]){
          flag = false;
        }
      }
    }else{
      flag = false;
    }
    if(!flag){
      succ = false;
      this.showInfo('两次密码不一致,请重新输入', 1000);
      this.lsPass.model = 2; // 由于密码不正确,重新回到 model 2
      this.updateMessage();
    }else{
      succ = true; // 密码正确,localStorage 存储,并设置状态为 model 1
      w.localStorage.setItem('HandLockPass', this.lsPass.temp.join('-')); // 存储字符串
      this.lsPass.model = 1;
      this.lsPass.pass = this.lsPass.temp;
      this.updateMessage();
    }
    delete this.lsPass.temp; // 很重要,一定要删掉,bug
  }else if(model == 1){ // 验证密码
    var tc = this.touchCircles, lp = this.lsPass.pass, flag = true;
    if(tc.length == lp.length){
      for(var i = 0; i < tc.length; i++){
        if(tc[i].id != lp[i]){
          flag = false;
        }
      }
    }else{
      flag = false;
    }
    if(!flag){
      succ = false;
      this.showInfo('很遗憾,密码错误', 1000);
    }else{
      succ = true;
      this.showInfo('恭喜你,验证通过', 1000);
    }
  }
},

密码的设置要参照前边那张图,要随时警惕状态的退换。

y: i *4* r +3* r

4. 手动重新设置密码

思路也不会细小略,正是增添点击事件,点击之后,改动 model 就可以,点击事件如下:

this.dom.setPass.add伊夫ntListener('click', function(e){ self.lsPass.model = 2; // 改换 model 为设置密码 self.updateMessage(); // 更新 message self.showInfo('请设置密码', 一千); }) this.dom.checkPass.add伊芙ntListener('click', function(e){ if(self.lsPass.pass){ self.lsPass.model = 1; self.updateMessage(); self.showInfo('请验证密码', 一千) }else{ self.showInfo('请先设置密码', 1000); self.updateMessage(); } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
this.dom.setPass.addEventListener('click', function(e){
  self.lsPass.model = 2; // 改变 model 为设置密码
  self.updateMessage(); // 更新 message
  self.showInfo('请设置密码', 1000);
})
this.dom.checkPass.addEventListener('click', function(e){
  if(self.lsPass.pass){
    self.lsPass.model = 1;
    self.updateMessage();
    self.showInfo('请验证密码', 1000)
  }else{
    self.showInfo('请先设置密码', 1000);
    self.updateMessage();
  }
})

ps:这里面还恐怕有多少个小的 bug,因为 model 独有 3 个,所以设置的时候,当点击复位密码的时候,未有设置密码成功,又切成验证密码状态,此时不也许擢升沿用旧密码,原因是 model 独有三个

});

5. 增添 touchend 颜色变化

贯彻那么些大致就马到功成了,那几个意义最重大的是给客商二个唤起,若客户划出的密码符合规范,展现士林蓝,若不符合规范或不当,彰显深藕红警戒。

因为在此之前曾经设置了四个 succ 变量,专门用于重绘。

JavaScript

drawEndCircles: function(color){ // end 时重绘已经 touch 的圆 for(var i = 0; i < this.touchCircles.length; i++){ this.drawCircle(this.touchCircles[i].x, this.touchCircles[i].y, color); } }, // 调用 if(succ){ this.drawEndCircles('#2CFF26'); // 绿色 }else{ this.drawEndCircles('red'); // 红色 }

1
2
3
4
5
6
7
8
9
10
11
12
drawEndCircles: function(color){ // end 时重绘已经 touch 的圆
  for(var i = 0; i < this.touchCircles.length; i++){
    this.drawCircle(this.touchCircles[i].x, this.touchCircles[i].y, color);
  }
},
 
// 调用
if(succ){
  this.drawEndCircles('#2CFF26'); // 绿色
}else{
  this.drawEndCircles('red'); // 红色
}

那就是说,三个足以演示的版本就生成了,就算还设有点bug,随后会来缓和。(详细的情况分支 password)

restPoint.push({

一些 bugs

稍许 bugs 在做的时候就意识了,一些 bug 后来用手提式有线电话机测验的时候才发掘,例如,作者用 chrome 的时候,未有意识这些bug,当本人用 android 手提式有线电话机 chrome 浏览器测验的时候,开掘当本人 touchmove 向下的时候,会触发浏览器的下拉刷新,化解办法:加了一个 preventDefault,没悟出依然成功了。

this.canvas.addEventListener('touchmove', function(e){ e.preventDefault ? e.preventDefault() : null; var p = self.getTouchPos(e); if(self.touchFlag){ self.update(p); }else{ self.judgePos(p); } }, false)

1
2
3
4
5
6
7
8
9
this.canvas.addEventListener('touchmove', function(e){
  e.preventDefault ? e.preventDefault() : null;
  var p = self.getTouchPos(e);
  if(self.touchFlag){
    self.update(p);
  }else{
    self.judgePos(p);
  }
}, false)

x: j *4* r +3* r,

关于 showInfo

出于showInfo 中有 setTimeout 函数,能够观望函数里的演艺为 1s,导致假诺大家操作的进度异常快,在 1s 内接连 show 了数不胜数个 info,前面包车型客车 info 会被第四个 info 的 setTimeout 弄乱,突显的日子低于 1s,或更加短。比方,当再一次点击设置手势密码和评释手势密码,会发生这些 bug。

化解办法有四个,二个是扩张贰个特别用于浮现的数组,每趟从数组中取值然后显示。另一种解题思路和防抖动的思绪很像,正是当有一个新的 show 到来时,把前边的那些 setTimeout 清除掉。

此处运用第二种思路:

showInfo: function(message, timer){ // 特意用来呈现 info clear提姆eout(this.showInfo.timer); var info = this.dom.info; info.innerHTML = message; info.style.display = 'block'; this.showInfo.timer = setTimeout(function(){ info.style.display = ''; }, timer || 1000) },

1
2
3
4
5
6
7
8
9
showInfo: function(message, timer){ // 专门用来显示 info
  clearTimeout(this.showInfo.timer);
  var info = this.dom.info;
  info.innerHTML = message;
  info.style.display = 'block';
  this.showInfo.timer = setTimeout(function(){
    info.style.display = '';
  }, timer || 1000)
},

y: i *4* r +3* r

消除小尾巴

所谓的小尾巴,如下:

澳门金莎娱乐网站 14

消除办法也不会细小略,在 touchend 的时候,先进行 clearRect 就 ok 了。

});

有关优化

个性优化一贯都以二个大标题,不要感觉前端不供给思考内部存款和储蓄器,就足以任由写代码。

事先在设计和煦网页的时候,用到了滚动,鼠标滑轮轻轻一碰,滚动函数就实践了几十多则几百次,以前也设想过消除办法。

}

优化 canvas 部分

对于 touchmove 函数,原理都是均等的,手指一划,就施行了 n 多次,那几个主题材料背后在消除,先来看另一个标题。

touchmove 是叁个往往函数,看到这里,假若你并未留意看自身的代码,这您对自己利用的 canvas 画图格局大概不太精通,下边那个是 touchmove 函数干了什么样事:

  1. 先剖断,借使当前处于未入选二个密码状态,则持续监视当前的职责,直到选中第4个密码,步向第二步;
  2. 进去 update 函数,update 函数根本干四件事,重绘圆(密码)、判定当前任务、重绘点、重绘线;

其次步是七个很牵挂的动作,为啥每回都要重绘圆,点和线呢?

澳门金莎娱乐网站 15

地方这一个图能够很好的验证难题,因为在安装或证实密码的历程中,大家必要用一条线来连接触点到最近的最终一个密码,並且当 touchmove 的时候,能来看它们在转移。那一个功用很棒,能够描绘出 touchmove 的轨迹。

可是,这就必须求随时刷新 canvas,品质大大地回降,刷新的那可是全体canvas。

因为 canvas 独有三个,既要画背景圆(密码),又要画已选密码的点,和折线。那其间大多步骤,一如在此之前只需求三次就好了,比方背景圆,只需在开发银行的时候画一次,已选密码,只要当 touchCircles 新英镑素的时候才会用壹遍,还不用重绘,只要画就能够了。折线分成两有些,一部分是已选密码之间的连线,还会有便是最后二个密码点到近来触点之间的连线。

假定有七个 canvas 就好了,一个囤积静态的,几个专门用于重绘

怎么不能有吗!

本人的化解思路是,今后有五个canvas,一个在尾部,作为描绘静态的圆、点和折线,另一个在上层,一方面监听 touchmove 事件,另一方面不停地重绘最终贰个密码点的圆心到近年来触点之间的线。倘诺这么可以的话,touchmove 函数实践三次的频率大大进步。

布置第2个 canvas:

var canvas2 = canvas.cloneNode(canvas, true); canvas2.style.position = 'absolute';//让上层 canvas 覆盖底层 canvas canvas2.style.top = '0'; canvas2.style.left = '0'; this.el.appendChild(canvas2); this.ctx2 = canvas2.getContext('2d');

1
2
3
4
5
6
var canvas2 = canvas.cloneNode(canvas, true);
canvas2.style.position = 'absolute';//让上层 canvas 覆盖底层 canvas
canvas2.style.top = '0';
canvas2.style.left = '0';
this.el.appendChild(canvas2);
this.ctx2 = canvas2.getContext('2d');

要改动对第贰个 ctx2 进行 touch 监听,并安装八个 this.reDraw 参数,表示有新的密码增多进去,需求对点和折线增添新内容, update 函数要改成这么:

update: function(p){ // 更新 touchmove this.judgePos(p); // 每回都要认清 this.drawLine2TouchPos(p); // 新加函数,用于绘最终二个密码点点圆心到触点之间的线 if(this.reDraw){ // 有新的密码加跻身 this.reDraw = false; this.drawPoints(); // 加多新点 this.drawLine();// 增添新线 } },

1
2
3
4
5
6
7
8
9
update: function(p){ // 更新 touchmove
  this.judgePos(p); // 每次都要判断
  this.drawLine2TouchPos(p); // 新加函数,用于绘最后一个密码点点圆心到触点之间的线
  if(this.reDraw){ // 有新的密码加进来
    this.reDraw = false;
    this.drawPoints(); // 添加新点
    this.drawLine();// 添加新线
  }
},

drawLine2TouchPos: function(p){ var len = this.touchCircles.length; if(len >= 1){ this.ctx2.clearRect(0, 0, this.width, this.width); // 先清空 this.ctx2.beginPath(); this.ctx2.lineWidth = 3; this.ctx2.moveTo(this.touchCircles[len - 1].x, this.touchCircles[len

  • 1].y); this.ctx2.lineTo(p.x, p.y); this.ctx2.stroke(); this.ctx2.closePath(); } },
1
2
3
4
5
6
7
8
9
10
11
12
drawLine2TouchPos: function(p){
  var len = this.touchCircles.length;
  if(len >= 1){
    this.ctx2.clearRect(0, 0, this.width, this.width); // 先清空
    this.ctx2.beginPath();
    this.ctx2.lineWidth = 3;
    this.ctx2.moveTo(this.touchCircles[len - 1].x, this.touchCircles[len - 1].y);
    this.ctx2.lineTo(p.x, p.y);
    this.ctx2.stroke();
    this.ctx2.closePath();
  }
},

对应的 drawPoints 和 drawLine 函数也要对应修改,由原理画全数的,到现行反革命只须求画新加的。

效率怎么着:

澳门金莎娱乐网站 16

move 函数实行数次,而其余函数唯有当新密码加进来的时候才实行贰次。

}

走入节流函数

事先也已经说过了,这么些 touchmove 函数执行的次数相当多,固然咱们已经用三个 canvas 对重绘做了相当大的优化,但 touchmove 照旧有一点大开辟。

其有时候小编想开了防抖动和节流,首先防抖动肯定是不行的,万一自个儿一向处在 touch 状态,重绘会延迟死的,这年节流会好有的。防抖和节流。

先写叁个节流函数:

throttle: function(func, delay, mustRun){ var timer, startTime = new Date(), self = this; return function(){ var curTime = new Date(), args = arguments; clearTimeout(timer); if(curTime - startTime >= mustRun){ startTime = curTime; func.apply(self, args); }else{ timer = setTimeout(function(){ func.apply(self, args); }, delay) } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
throttle: function(func, delay, mustRun){
  var timer, startTime = new Date(), self = this;
  return function(){
    var curTime = new Date(), args = arguments;
    clearTimeout(timer);
    if(curTime - startTime >= mustRun){
      startTime = curTime;
      func.apply(self, args);
    }else{
      timer = setTimeout(function(){
        func.apply(self, args);
      }, delay)
    }
  }
}

节流函数的意味:在延迟为 delay 的时日内,如果函数再一次接触,则重新计时,这么些职能和防抖动是平等的,第多少个参数 mustRun 是贰个光阴世隔,表示在时间距离大于 mustRun 后的二个函数能够即刻直接实行。

下一场对 touchmove 的回调函数实行退换:

var t = this.throttle(function(e){ e.preventDefault ? e.preventDefault() : null; e.stopPropagation ? e.stopPropagation() : null; var p = this.getTouchPos(e); if(this.touchFlag){ this.update(p); }else{ this.judgePos(p); } }, 16, 16) this.canvas2.addEventListener('touchmove', t, false)

1
2
3
4
5
6
7
8
9
10
11
var t = this.throttle(function(e){
  e.preventDefault ? e.preventDefault() : null;
  e.stopPropagation ? e.stopPropagation() : null;
  var p = this.getTouchPos(e);
  if(this.touchFlag){
    this.update(p);
  }else{
    this.judgePos(p);
  }
}, 16, 16)
this.canvas2.addEventListener('touchmove', t, false)

有关 delay 和 mustRun 的日子间隔难点,web 质量里有一个 16ms 的定义,就是说假如要达到规定的规范每秒 60 帧,间隔为 一千/60 大概为 16 ms。若是距离大于 16ms 则 fps 会比 60 低。

鉴于此,咱们那边将 delay 和 mustRun 都设为 16,在无比的动静下,也便是最坏的气象下,或者须求 15 + 15 = 30ms 才会实践一回,今年要安装四个 8 才创设,可是牵记到手指运动是多个一而再的进程,怎么恐怕会每 15 秒奉行叁回,经过在线测量检验,发掘安装成 16 效果勉强能够。

脾气真的能优化吗,我们来看多个图片,do 和 wantdo 表示真实实施和停放节流函数中排队准备实践。

当 touchmove 速度一般或飞跃的时候:

澳门金莎娱乐网站 17

当 touchmove 速度非常的慢的时候:

澳门金莎娱乐网站 18

能够看出来,滑动进度中,速度一般和高效,平均优化了一半,慢速效果也优化了 20 到 30%之间,日常手势锁解锁时候,显明速度比异常快。可知,节流的优化照旧很确定的。

珍视是,优化今后的流程性,未有面对别的影响。

其一节流函数最后照旧现身了一个 bug:由于是延迟实施的,导致 e.preventDefault 失效,在三哥大浏览器向下滑会油然则生刷新的状态,那也算事件延迟的四个损害呢。

化解办法:在节流函数提前裁撤默许事件:

throttle: function(func, delay, mustRun){ var timer, startTime = new Date(), self = this; return function(e){ if(e){ e.preventDefault ? e.preventDefault() : null; //提前打消默许事件,不要等到 set提姆eout e.stopPropagation ? e.stopPropagation() : null; } ... } }

1
2
3
4
5
6
7
8
9
10
throttle: function(func, delay, mustRun){
  var timer, startTime = new Date(), self = this;
  return function(e){
    if(e){
      e.preventDefault ? e.preventDefault() : null; //提前取消默认事件,不要等到 setTimeout
      e.stopPropagation ? e.stopPropagation() : null;
    }
    ...
  }
}

//return arr;

总结

粗粗花了二十七日左右的日子,将以此 H5 的手势解锁给完了,自个儿大概比较满足的,即便或然达不到评选委员会委员老师的承认,可是自个儿在做的进度中,学习到了众多新知识。

}

参考

H5lock
Canvas教程
js获取单选框里面包车型的士值
前端高质量滚动 scroll 及页面渲染优化

3 赞 5 收藏 评论

澳门金莎娱乐网站 19

canvas里的圆形画好之后方可扩充事件绑定

functionbindEvent(){

can.addEventListener("touchstart",function(e){

varpo = getPosition(e);

console.log(po);

for(vari =0; i < arr.length ; i++) {

if(Math.abs(po.x - arr[i].x) < r &&Math.abs(po.y - arr[i].y) < r) {// 用来决断最初点是还是不是在规模内部

touchFlag =true;

drawPoint(arr[i].x,arr[i].y);

lastPoint.push(arr[i]);

restPoint.splice(i,1);

break;

}

}

},false);

can.addEventListener("touchmove",function(e){

if(touchFlag) {

update(getPosition(e));

}

},false);

can.addEventListener("touchend",function(e){

if(touchFlag) {

touchFlag =false;

storePass(lastPoint);

setTimeout(function(){

init();

},300);

}

},false);

}

进而到了最重视的步骤绘制解锁路线逻辑,通过touchmove事件的处处触发,调用canvas的moveTo方法和lineTo方法来画出折现,同不常等候法庭判果决是或不是达到大家所画的层面里面,在那之中lastPoint保存不易的范围路线,restPoint保存全体范围去除正确渠道之后剩余的。 Update方法:

functionupdate(po){// 大旨转移格局在touchmove时候调用

ctx.clearRect(0,0, ctx.canvas.width, ctx.canvas.height);

for(vari =0; i < arr.length ; i++) {// 每帧先把面板画出来

drawCle(arr[i].x, arr[i].y);

}

drawPoint(lastPoint);// 每帧花轨迹

drawLine(po , lastPoint);// 每帧画圆心

for(vari =0; i < restPoint.length ; i++) {

if(Math.abs(po.x - restPoint[i].x) < r &&Math.abs(po.y - restPoint[i].y) < r) {

drawPoint(restPoint[i].x, restPoint[i].y);

lastPoint.push(restPoint[i]);

restPoint.splice(i,1);

break;

}

}

}

最终正是结束工作,把路子里面包车型客车lastPoint保存的数组产生密码存在localstorage里面,之后就用来拍卖解锁验证逻辑了

functionstorePass(psw){// touchend甘休之后对密码和情景的管理

if(pswObj.step ==1) {

if(checkPass(pswObj.fpassword, psw)) {

pswObj.step =2;

pswObj.spassword = psw;

document.getElementById('title').innerHTML ='密码保存成功';

drawStatusPoint('#2CFF26');

window.localStorage.setItem('passwordx',JSON.stringify(pswObj.spassword));

window.localStorage.setItem('chooseType', chooseType);

}else{

document.getElementById('title').innerHTML ='两回不均等,重新输入';

drawStatusPoint('red');

deletepswObj.step;

}

}elseif(pswObj.step ==2) {

if(checkPass(pswObj.spassword, psw)) {

document.getElementById('title').innerHTML ='解锁成功';

drawStatusPoint('#2CFF26');

}else{

drawStatusPoint('red');

document.getElementById('title').innerHTML ='解锁战败';

}

}else{

pswObj.step =1;

pswObj.fpassword = psw;

document.getElementById('title').innerHTML ='再一次输入';

}

}

本文由澳门金莎娱乐网站发布于澳门金莎娱乐网站,转载请注明出处:手势解锁,HTML5实现屏幕手势解锁

关键词:

最近学习JS的感悟,组件化的Web王国

自定义标签在IE6-8的困境 2015/07/20 · HTML5 ·IE,自定义标签 原文出处:司徒正美    或许未来前端组件化之路都是自定...

详细>>

是时候再提web标准,前端编码规范

1、门槛低、简单 一周就可以掌握html,常用标签不多,用不到的不用管 比如:h1~6、p、span、div、img、a、input等,我们...

详细>>

登录工程,应用中的身份验证技术

登录工程:现代 Web 应用的典型身份验证需求 2017/02/18 · 基础技术 ·WEB,登录,身份验证 本文作者: 伯乐在线 -ThoughtW...

详细>>

年的所见所得,从草根到英雄

Web 开发 17 年的所见所得 2017/07/10 · 基础技术 ·WEB,开发建议 原文出处: DanielKhan   译文出处:众成翻译/myvin    英...

详细>>