HTML5落实显示器手势解锁(转发),html5手势

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

来源:

(JSCity:把源码可视化成建筑物的 JS 库)

(Web前端 腾讯AlloyTeam Blog )
JS 库)

HTML5实现屏幕手势解锁(转载),html5手势

来源:

(JSCity:把源码可视化成建筑物的 JS 库)

(Web前端 腾讯AlloyTeam Blog )
JS 库)

JS:

(function(){
        window.H5lock = function(obj){
            this.height = obj.height;
            this.width = obj.width;
            this.chooseType = Number(window.localStorage.getItem('chooseType')) || obj.chooseType;
        };


        H5lock.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();
        }
        H5lock.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();
            }
        }
        H5lock.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();
            }
        }
        H5lock.prototype.drawLine = function(po, lastPoint) {// 解锁轨迹
            this.ctx.beginPath();
            this.ctx.lineWidth = 3;
            this.ctx.moveTo(this.lastPoint[0].x, this.lastPoint[0].y);
            console.log(this.lastPoint.length);
            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();

        }
        H5lock.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;
        }
        H5lock.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;
        }
        H5lock.prototype.update = function(po) {// 核心变换方法在touchmove时候调用
            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);
            }

            this.drawPoint(this.lastPoint);// 每帧花轨迹
            this.drawLine(po , this.lastPoint);// 每帧画圆心

            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.restPoint[i].x, this.restPoint[i].y);
                    this.lastPoint.push(this.restPoint[i]);
                    this.restPoint.splice(i, 1);
                    break;
                }
            }

        }
        H5lock.prototype.checkPass = function(psw1, psw2) {// 检测密码
            var p1 = '',
            p2 = '';
            for (var i = 0 ; i < psw1.length ; i++) {
                p1 += psw1[i].index + psw1[i].index;
            }
            for (var i = 0 ; i < psw2.length ; i++) {
                p2 += psw2[i].index + psw2[i].index;
            }
            return p1 === p2;
        }
        H5lock.prototype.storePass = function(psw) {// touchend结束之后对密码和状态的处理
            if (this.pswObj.step == 1) {
                if (this.checkPass(this.pswObj.fpassword, psw)) {
                    this.pswObj.step = 2;
                    this.pswObj.spassword = psw;
                    document.getElementById('title').innerHTML = '密码保存成功';
                    this.drawStatusPoint('#2CFF26');
                    window.localStorage.setItem('passwordxx', JSON.stringify(this.pswObj.spassword));
                    window.localStorage.setItem('chooseType', this.chooseType);
                } else {
                    document.getElementById('title').innerHTML = '两次不一致,重新输入';
                    this.drawStatusPoint('red');
                    delete this.pswObj.step;
                }
            } else if (this.pswObj.step == 2) {
                if (this.checkPass(this.pswObj.spassword, psw)) {
                    document.getElementById('title').innerHTML = '解锁成功';
                    this.drawStatusPoint('#2CFF26');
                } else {
                    this.drawStatusPoint('red');
                    document.getElementById('title').innerHTML = '解锁失败';
                }
            } else {
                this.pswObj.step = 1;
                this.pswObj.fpassword = psw;
                document.getElementById('title').innerHTML = '再次输入';
            }

        }
        H5lock.prototype.makeState = function() {
            if (this.pswObj.step == 2) {
                document.getElementById('updatePassword').style.display = 'block';
                //document.getElementById('chooseType').style.display = 'none';
                document.getElementById('title').innerHTML = '请解锁';
            } else if (this.pswObj.step == 1) {
                //document.getElementById('chooseType').style.display = 'none';
                document.getElementById('updatePassword').style.display = 'none';
            } else {
                document.getElementById('updatePassword').style.display = 'none';
                //document.getElementById('chooseType').style.display = 'block';
            }
        }
        H5lock.prototype.setChooseType = function(type){
            chooseType = type;
            init();
        }
        H5lock.prototype.updatePassword = function(){
            window.localStorage.removeItem('passwordxx');
            window.localStorage.removeItem('chooseType');
            this.pswObj = {};
            document.getElementById('title').innerHTML = '绘制解锁图案';
            this.reset();
        }
        H5lock.prototype.initDom = function(){
            var wrap = document.createElement('div');
            var str = '<h4 id="title" class="title">绘制解锁图案</h4>'+
                      '<a id="updatePassword"><!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>H5lock</title>
    <style type="text/css">
        body {
            text-align: center;
            background-color: #305066;
        }
        .title {
            color: #22C3AA;
        }
    </style>

    </head>
<body>
<script type="text/javascript" src="javascripts/H5lock.js"></script>
<script type="text/javascript">
//http://www.nihaoshijie.com.cn/index.php/archives/537http://www.nihaoshijie.com.cn/index.php/archives/537
 /* 
http://top.jobbole.com/22960/
 http://threejs.org/examples/
http://www.inf.usi.ch/phd/wettel/codecity-download.html
https://github.com/lvming6816077/H5lock
HTML5 实现屏幕手势解锁
*/ new H5lock({ chooseType: 3 }).init(); </script> </body> </html>

  

来源:

图片 4

图片 5图片 6

JS:

实现原理利用HTML5的canvas,将解锁的圈圈划出,利用touch事件解锁这些圈圈,直接看代码。

 

(function(){
        window.H5lock = function(obj){
            this.height = obj.height;
            this.width = obj.width;
            this.chooseType = Number(window.localStorage.getItem('chooseType')) || obj.chooseType;
        };


        H5lock.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();
        }
        H5lock.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();
            }
        }
        H5lock.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();
            }
        }
        H5lock.prototype.drawLine = function(po, lastPoint) {// 解锁轨迹
            this.ctx.beginPath();
            this.ctx.lineWidth = 3;
            this.ctx.moveTo(this.lastPoint[0].x, this.lastPoint[0].y);
            console.log(this.lastPoint.length);
            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();

        }
        H5lock.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;
        }
        H5lock.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;
        }
        H5lock.prototype.update = function(po) {// 核心变换方法在touchmove时候调用
            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);
            }

            this.drawPoint(this.lastPoint);// 每帧花轨迹
            this.drawLine(po , this.lastPoint);// 每帧画圆心

            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.restPoint[i].x, this.restPoint[i].y);
                    this.lastPoint.push(this.restPoint[i]);
                    this.restPoint.splice(i, 1);
                    break;
                }
            }

        }
        H5lock.prototype.checkPass = function(psw1, psw2) {// 检测密码
            var p1 = '',
            p2 = '';
            for (var i = 0 ; i < psw1.length ; i++) {
                p1 += psw1[i].index + psw1[i].index;
            }
            for (var i = 0 ; i < psw2.length ; i++) {
                p2 += psw2[i].index + psw2[i].index;
            }
            return p1 === p2;
        }
        H5lock.prototype.storePass = function(psw) {// touchend结束之后对密码和状态的处理
            if (this.pswObj.step == 1) {
                if (this.checkPass(this.pswObj.fpassword, psw)) {
                    this.pswObj.step = 2;
                    this.pswObj.spassword = psw;
                    document.getElementById('title').innerHTML = '密码保存成功';
                    this.drawStatusPoint('#2CFF26');
                    window.localStorage.setItem('passwordxx', JSON.stringify(this.pswObj.spassword));
                    window.localStorage.setItem('chooseType', this.chooseType);
                } else {
                    document.getElementById('title').innerHTML = '两次不一致,重新输入';
                    this.drawStatusPoint('red');
                    delete this.pswObj.step;
                }
            } else if (this.pswObj.step == 2) {
                if (this.checkPass(this.pswObj.spassword, psw)) {
                    document.getElementById('title').innerHTML = '解锁成功';
                    this.drawStatusPoint('#2CFF26');
                } else {
                    this.drawStatusPoint('red');
                    document.getElementById('title').innerHTML = '解锁失败';
                }
            } else {
                this.pswObj.step = 1;
                this.pswObj.fpassword = psw;
                document.getElementById('title').innerHTML = '再次输入';
            }

        }
        H5lock.prototype.makeState = function() {
            if (this.pswObj.step == 2) {
                document.getElementById('updatePassword').style.display = 'block';
                //document.getElementById('chooseType').style.display = 'none';
                document.getElementById('title').innerHTML = '请解锁';
            } else if (this.pswObj.step == 1) {
                //document.getElementById('chooseType').style.display = 'none';
                document.getElementById('updatePassword').style.display = 'none';
            } else {
                document.getElementById('updatePassword').style.display = 'none';
                //document.getElementById('chooseType').style.display = 'block';
            }
        }
        H5lock.prototype.setChooseType = function(type){
            chooseType = type;
            init();
        }
        H5lock.prototype.updatePassword = function(){
            window.localStorage.removeItem('passwordxx');
            window.localStorage.removeItem('chooseType');
            this.pswObj = {};
            document.getElementById('title').innerHTML = '绘制解锁图案';
            this.reset();
        }
        H5lock.prototype.initDom = function(){
            var wrap = document.createElement('div');
            var str = '<h4 id="title" class="title">绘制解锁图案</h4>'+
                      '<a id="updatePassword" style="position: absolute;right: 5px;top: 5px;color:#fff;font-size: 10px;display:none;">重置密码</a>'+
                      '<canvas id="canvas" width="300" height="300" style="background-color: #305066;display: inline-block;margin-top: 15px;"></canvas>';
            wrap.setAttribute('style','position: absolute;top:0;left:0;right:0;bottom:0;');
            wrap.innerHTML = str;
            document.body.appendChild(wrap);
        }
        H5lock.prototype.init = function() {
            this.initDom();
            this.pswObj = window.localStorage.getItem('passwordxx') ? {
                step: 2,
                spassword: JSON.parse(window.localStorage.getItem('passwordxx'))
            } : {};
            this.lastPoint = [];
            this.makeState();
            this.touchFlag = false;
            this.canvas = document.getElementById('canvas');
            this.ctx = this.canvas.getContext('2d');
            this.createCircle();
            this.bindEvent();
        }
        H5lock.prototype.reset = function() {
            this.makeState();
            this.createCircle();
        }
        H5lock.prototype.bindEvent = function() {
            var self = this;
            this.canvas.addEventListener("touchstart", function (e) {
                e.preventDefault();// 某些android 的 touchmove不宜触发 所以增加此行代码
                 var po = self.getPosition(e);
                 console.log(po);
                 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.drawPoint(self.arr[i].x,self.arr[i].y);
                        self.lastPoint.push(self.arr[i]);
                        self.restPoint.splice(i,1);
                        break;
                    }
                 }
             }, false);
             this.canvas.addEventListener("touchmove", function (e) {
                if (self.touchFlag) {
                    self.update(self.getPosition(e));
                }
             }, false);
             this.canvas.addEventListener("touchend", function (e) {
                 if (self.touchFlag) {
                     self.touchFlag = false;
                     self.storePass(self.lastPoint);
                     setTimeout(function(){

                        self.reset();
                    }, 300);
                 }


             }, false);
             document.addEventListener('touchmove', function(e){
                e.preventDefault();
             },false);
             document.getElementById('updatePassword').addEventListener('click', function(){
                 self.updatePassword();
              });
        }
})();

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

早上花了一个半小时写了一个基于HTML
Canvas的手势解锁,主要是为了好玩,可能以后会用到。

  HTML5:

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

思路:根据配置计算出九个点的位置,存入一个数组,当然存入数组的顺序的索引是:

<!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>H5lock</title>
    <style type="text/css">
        body {
            text-align: center;
            background-color: #305066;
        }
        .title {
            color: #22C3AA;
        }
    </style>

    </head>
<body>
<script type="text/javascript" src="javascripts/H5lock.js"></script>
<script type="text/javascript">
//http://www.nihaoshijie.com.cn/index.php/archives/537http://www.nihaoshijie.com.cn/index.php/archives/537
 /* 
http://top.jobbole.com/22960/
 http://threejs.org/examples/
http://www.inf.usi.ch/phd/wettel/codecity-download.html
https://github.com/lvming6816077/H5lock
HTML5 实现屏幕手势解锁
*/ new H5lock({ chooseType: 3 }).init(); </script> </body> </html>

lastPoint = [];

   第一行:0   1  2    第二行:3  4  5   第三行:6  7  8

  

arr = [];

        然后就根据这个坐标数组去绘制九个点

微软在MIT下开源DirectX工具集最新开源的软件包括了:DirectX Tool
Kit,DirectXTex,DirectXMesh,UVAtlas,Effects 11,DXUT11,Sample
Content Exporter等等。

restPoint = [];

       
再则我们需要一个保存选中点的数组,每当touchmove事件就判断当前触摸点和那个点的距离小于圆的半径

随着Web技术的不断发展,前端开发框架层出不穷,各有千秋,开发者在做技术选型时总是要费一番脑筋,最近,IBM高级工程师王芳侠撰文对Bootstrap、jQuery
UI、jQuery Mobile、Sencha ExtJS、Sencha Touch、Sencha GXT、Dojo、Dojo
Mobile、Mootools、Foundation、YUI、Kissy、QWrap 等 16
个国内外前端开发框架进行了比较详细的比较,非常值得读者借鉴。

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

    如果为真的话 那么就添加进入选中点的数组

从国外的桌面端框架来说,作者认为主要有以下几个:

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

    在绘制过程中就根据该数据去绘制线条。就这么简单 

  • Bootstrap主要针对桌面端市场,Bootstrap3
    提出移动优先,不过目前桌面端依然还是 Bootstrap
    的主要目标市场。Bootstrap 主要基于 jQuery 进行 JavaScript 处理,支持
    LESS 来做 CSS 的扩展。如果想要在 Bootstrap 框架中使用
    Sass,则需要通过
    Bootstrap-Sass项目增加兼容。Bootstrap
    框架在布局、版式、控件、特效方面都非常让人满意,都预置了丰富的效果,极大方便了用户开发。在风格设置方面,还需要用户在下载时手动设置,可配置粒度非常细,相应也比较繁琐,不太直观,需要对
    Bootstrap 非常熟悉配置起来才能得心应手。
  • jQuery UI是 jQuery
    项目组中对桌面端的扩展,包括了丰富的控件和特效,与 jQuery
    无缝兼容。同时,jQuery UI
    中预置了多种风格供用户选择,避免了千篇一律。如果您对预置的风格不满意,还可以通过
    jQuery UI 的可视化界面,自助对 jQuery UI
    的显示效果进行配置,非常方便,够高端大气上档次。
  • Sencha Ext JS是 Sencha 基于
    Ext JS
    开发的前端框架,内容极其丰富,控件、特效等支持非常非常丰富,表格、图画、报告、布局、甚至数据连接,无所不包。只有您想不到,没有它办不到。基于
    Sass 和 Compass,使得用户对格式的修改和特效制作更加方便。商业化是
    Sencha 的另一把利剑。帮助 Sencha
    披荆斩棘之时,也把大把的码农砍在马下。Sencha
    规定,凡是商业化的应用,都需要付费。另外,Sencha
    的辅助产品也全部收费,否则只能是试用版。
  • Dojo,目前唯一能与 Sencha Ext JS
    一较高下的框架就只有 Dojo了。抱着 IBM、VMWare 等众多大腿,Dojo
    的一颦一笑都额外惹人注目。Dojo
    项目的产品线和功能也特别丰富。首先,Dojo 有自己的 DOM 解析器
    Nano,是 DOM 解析和处理的内核。此外,Dojo 的 Web
    框架有非常丰富的布局、版式、控件以及特效,对多语言以及图表的扩展支持都非常好,并支持对地图的操作。大家可以查看它的演示,与
    Ext JS 的效果进行比较。此外,Dojo 还有自己的图形化设计和开发工具
    Maqetta,可以通过拖拽实现设计。Dojo
    的风格设置不是在下载的时候指定的,而是通过引用不同的 CSS
    格式来实现。
  • Mootools可以说是目前最轻量级的前端框架,内核
    js 压缩完之后只有 8k,完整版压缩之后也不到
    100k,远比其他框架要小很多。Mootools 有自己的面向对象设计的内核
    Mootools
    Core。伴随着最小的文件大小,框架的功能比其他框架也要弱不少,只有在控件和特效上有少量支持。
  • Prototype
    JS也是一个简洁的框架,有着丰富的对 DOM
    操作的功能,对 Ajax 和 JSON 支持得都非常好,在使用上与 jQuery
    相比也相差不多。作为 Rails 默认的 JavaScript
    框架,相信对广大开发人员也很有借鉴意义的。
  • YUI作为开源前端框架的鼻祖,在框架上的功力非常之深。有着自己的解析
    DOM
    的核心框架,并且在特效、动画、图表等方面都有丰富的扩展,并可以通过
    YQL 直接访问
    Yahoo!的数据。在用户经常使用的功能方面都有着不错的表现。与 jQuery
    灵活的语法相比,YUI
    显得更加中规中矩,在代码组织、结构和模式方面都更加讲究,更体现出工程师的严谨。

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

上代码:(需要chrome浏览器或者火狐浏览器 模拟手机状态才有触摸效果)

对于国内的前端开发框架,作者也做了分析:

arr.push({

 

  • Kissy是阿里集团自主开发的前端框架,目前在淘宝网、一淘网等阿里系网站上得到不少应用。Kissy
    框架模仿 jQuery 编写了自己的内核 Kissy Core,用于对 DOM 的解析,Ajax
    处理等。同时,有着丰富的控件,并实现了一些动画效果和特效。同样,在
    Kissy 的控件中也可以看到 Bootstrap 等国外框架的影子。此外,Kissy abc
    项目工具可以帮助用户实现自动化构建,并有很多扩展组件方便用户使用。
  • Qwrap是百度有啊团队推出的 JavaScript
    框架,现在被收入 360,被广泛应用与 360 产品中。Qwrap 综合
    jQuery、Prototype、YUI 特点,对 JavaScript
    进行了封装。但是,如果要把 Qwrap
    算成一个前端开发框架还是有些牵强,因为除了 JavaScript
    类库之外,Qwrap 基本乏善可陈,还处于发展阶段。
  • Tangram是百度推出的另一个 JavaScript
    框架,被广泛应用于百度系旗下的产品,与 Qwrap 类似,Tangram
    也只能算是一个 JavaScript 框架,对 JavaScript
    做了不少扩展,但是作为前端开发框架还是显得比较单薄。基于此,百度公司继续推出了两个基于
    Tangram 的项目,Magic 和 Baidu Template。

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

按 Ctrl+C 复制代码

 

y: i *4* r +3* r

<!DOCTYPE html> <html> <head lang=”en”> <meta
content=”width=device-width, initial-scale=1.0, maximum-scale=1.0,
user-scalable=0″ name=”viewport”/> <meta charset=”UTF-8″>
<title></title> <style type=”text/css”> html, body {
margin: 0; padding: 0; width: 100%; height: 100%; } </style>
<script type=”text/javascript”> var R = 26, CW = 400, CH = 320,
OffsetX = 30, OffsetY = 30; function CaculateNinePointLotion(diffX,
diffY) { var Re = []; for (var row = 0; row < 3; row++) { for (var
col = 0; col < 3; col++) { var Point = { X: (OffsetX + col * diffX +
( col * 2 + 1) * R), Y: (OffsetY + row * diffY + (row * 2 + 1) * R)
}; Re.push(Point); } } return Re; } var PointLocationArr = [];
window.onload = function () { var c =
document.getElementById(“myCanvas”); CW = document.body.offsetWidth;
c.width = CW; c.height = CH; var cxt = c.getContext(“2d”);
//两个圆之间的外距离 就是说两个圆心的距离去除两个半径 var X = (CW – 2 *
OffsetX – R * 2 * 3) / 2; var Y = (CH – 2 * OffsetY – R * 2 * 3) /
2; PointLocationArr = CaculateNinePointLotion(X, Y); InitEvent(c, cxt);
//CW=2*offsetX+R*2*3+2*X Draw(cxt, PointLocationArr, [],null); }
function Draw(cxt, _PointLocationArr, _LinePointArr,touchPoint) { if
(_LinePointArr.length > 0) { cxt.beginPath(); for (var i = 0; i <
_LinePointArr.length; i++) { var pointIndex = _LinePointArr[i];
cxt.lineTo(_PointLocationArr[pointIndex].X,
_PointLocationArr[pointIndex].Y); } cxt.lineWidth = 10;
cxt.strokeStyle = “#627eed”; cxt.stroke(); cxt.closePath();
if(touchPoint!=null) { var
lastPointIndex=_LinePointArr[_LinePointArr.length-1]; var
lastPoint=_PointLocationArr[lastPointIndex]; cxt.beginPath();
cxt.moveTo(lastPoint.X,lastPoint.Y);
cxt.lineTo(touchPoint.X,touchPoint.Y); cxt.stroke(); cxt.closePath(); }
} for (var i = 0; i < _PointLocationArr.length; i++) { var Point =
_PointLocationArr[i]; cxt.fillStyle = “#627eed”; cxt.beginPath();
cxt.arc(Point.X, Point.Y, R, 0, Math.PI * 2, true); cxt.closePath();
cxt.fill(); cxt.fillStyle = “#ffffff”; cxt.beginPath();
cxt.arc(Point.X, Point.Y, R – 3, 0, Math.PI * 2, true);
cxt.closePath(); cxt.fill(); if(_LinePointArr.indexOf(i)>=0) {
cxt.fillStyle = “#627eed”; cxt.beginPath(); cxt.arc(Point.X, Point.Y, R
-16, 0, Math.PI * 2, true); cxt.closePath(); cxt.fill(); } } } function
IsPointSelect(touches,LinePoint) { for (var i = 0; i <
PointLocationArr.length; i++) { var currentPoint =
PointLocationArr[i]; var xdiff = Math.abs(currentPoint.X –
touches.pageX); var ydiff = Math.abs(currentPoint.Y – touches.pageY);
var dir = Math.pow((xdiff * xdiff + ydiff * ydiff), 0.5); if (dir <
R ) { if(LinePoint.indexOf(i) < 0){ LinePoint.push(i);} break; } } }
function InitEvent(canvasContainer, cxt) { var LinePoint = [];
canvasContainer.addEventListener(“touchstart”, function (e) {
IsPointSelect(e.touches[0],LinePoint); }, false);
canvasContainer.addEventListener(“touchmove”, function (e) {
e.preventDefault(); var touches = e.touches[0];
IsPointSelect(touches,LinePoint); cxt.clearRect(0,0,CW,CH);
Draw(cxt,PointLocationArr,LinePoint,{X:touches.pageX,Y:touches.pageY});
}, false); canvasContainer.addEventListener(“touchend”, function (e) {
cxt.clearRect(0,0,CW,CH); Draw(cxt,PointLocationArr,LinePoint,null);
alert(“密码结果是:”+LinePoint.join(“->”)); LinePoint=[]; },
false); } </script> </head> <body> <canvas
id=”myCanvas”></canvas> </body> </html>

 

});

按 Ctrl+C 复制代码

 

restPoint.push({

 

2015 年最棒的 5 个 HTML5 框架

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


1.ionic

Advanced HTML5 mobile development framework and SDK. Build incredible
mobile apps with web technologies you already know and love. Best
friends with AngularJS.

y: i *4* r +3* r

2.Siimpler
Siimpler enables you to build your HTML5 starting boilerplate by
selecting the parts which you want to include.

});

3.Foundation

}

4.LimeJS
LimeJS is a HTML5 game framework for building fast, native-experience
games for all modern touchscreens and
desktop browsers.

}

5.Enyo

Use Enyo to develop apps for all major platforms, from phones and
tablets to PCs and TVs

//return arr;

}

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 =’再次输入’;

}

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注