澳门在线威尼斯官方 > 威尼斯澳门在线 > 威尼斯澳门在线HTML5兑现显示器手势解锁,手势解

原标题:威尼斯澳门在线HTML5兑现显示器手势解锁,手势解

浏览次数:129 时间:2019-09-24

用 canvas 实现 Web 手势解锁

2017/04/04 · HTML5 · Canvas

初稿出处: songjz   

近些日子在座 360 暑假的前端星布署,有贰个在线作业,甘休日期是 3 月 30 号,让手动达成三个 H5 手势解锁,具体的效劳就像是原新手提式有线电话机的九宫格解锁这样。

威尼斯澳门在线 1

福衢寿车的尾声效果就疑似下面那张图那样:

威尼斯澳门在线 2

主干必要是那般的:将密码保存到 localStorage 里,起初的时候会从地点读取密码,若无就让客商设置密码,密码最少为五位数,少于伍个人要升迁错误。须要对第一次输入的密码进行认证,一遍同样技能维系,然后是印证密码,能够对顾客输入的密码举办表达。

HTML5完成显示器手势解锁

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

初稿出处: AlloyTeam   

成效体现

威尼斯澳门在线 3

落到实处原理 利用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解锁写成了贰个组件,放在

二维码体验: 威尼斯澳门在线 4

 

参谋资料:

1 赞 4 收藏 1 评论

威尼斯澳门在线 5

H5 手势解锁

扫码在线查看:

威尼斯澳门在线 6

依旧点击查看手机版。

项目 GitHub 地址,H5HandLock。

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

自身感觉二个相比较合理的解法应该是应用 canvas 来贯彻,不明白有未有大神用 css 来完结。就算纯用 css 的话,能够将连线先安装 display: none,当手指划过的时候,展现出来。光设置这几个本该就十一分麻烦呢。

在此以前领悟过 canvas,但从不真的的写过,上面就来介绍自身近来学习 canvas 并促成 H5 手势解锁的进程。

企图及布局设置

自小编这里用了四个比较平常的做法:

(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 的话,懒得去新建文件了,就一向內联了。

canvas

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

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 事件了。

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;
    }
  }
}

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 手势解锁的简易版已经主导实现。

password

为了要兑现记住和重新载入参数密码的效应,把 password 保存在 localStorage 中,但首先要加上须求的 html 和体制。

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();

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 中呢。

本文由澳门在线威尼斯官方发布于威尼斯澳门在线,转载请注明出处:威尼斯澳门在线HTML5兑现显示器手势解锁,手势解

关键词:

上一篇:正史衍变与Normalize,书写规范

下一篇:没有了