亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > HTML5 > 正文

h5使用canvas畫布實現手勢解鎖

2024-09-05 07:22:46
字體:
來源:轉載
供稿:網友

前言

最近做的一個app項目使用的 apicloud 來實現跨平臺開發,現在需要為這個 app 添加手勢(九宮格)解鎖的功能,apicloud 已經有一些第三方的原生實現的手勢解鎖插件,因為是原生的性能也比較好,調用也比較方便,但是都不能對它們的樣式做修改,所以就打算自己來實現這個功能。這篇文章將實現過程整理分享出來,希望有需要的可以了解。分享出來的代碼只實現了最基本的 設置密碼功能解鎖功能 、 比較密碼 的功能等,一些高級功能例如:不能限制一個點最多經過多少次、限制用戶設置密碼的長度。

原生實現還是其它方式實現?

1、使用 android 和 ios 對應的平臺通過原生代碼來寫手勢解鎖插件。體驗好,但是開發周期長,需要處理各平臺的兼容性問題,并且需要學習apicloud平臺插件編寫方法。(放棄)

2、使用 html5 的 canvas 畫布來實現。開發周期短,不需要過多的處理兼容性問題,體驗好。(選擇)

原理分析

手勢解鎖

通過手指將屏幕上的九個點依次連接起來形成一個圖案,所以叫圖案解鎖。如上圖每一個解鎖圓圈后面其實都是一個數字,每次比較的并不是是用戶畫出來的圖案,而是每次手指經過圖案時串聯起來的圓圈下的數字組成的密碼字符串,本質上我們比較的還是字符串的密碼,只不過站在用戶的角度看是繪制出來的圖案。圖案的記憶遠比數字字符串記的牢固。

實現步驟

繪制密碼盤

密碼盤的繪制比較簡單,唯一需要注意需要通過動態計算使九個點圍成的正方式始終在屏幕的中間位置,在手機上還需要減去狀態欄的高度。

var width = $(document).width();var height = $(document).height() - 40; //減去手機狀態欄的高度//九宮格其實就是九個點,9個點的坐標對象var lockCicle = {    x: 0, //x坐標    y: 0, //y坐標    color: "#999999",    state: "1" //狀態當前點是否已經被鏈接過};var offset = (width - height) / 2; //計算偏移量var arr = []; //九個點的坐標數組//計算九個點坐標的方法for (var i = 1; i <= 3; i++) {    //每一行    for (var j = 1; j <= 3; j++) {        //每一行的每一個        var lockCicle = {};        //橫屏        if (offset > 0) {            lockCicle.x = (height / 4) * j + Math.abs(offset);            lockCicle.y = (height / 4) * i;            lockCicle.state = 0;            //豎屏        } else {            lockCicle.x = (width / 4) * j;            lockCicle.y = (width / 4) * i + Math.abs(offset);            lockCicle.state = 0;        }        arr.push(lockCicle);    }}//初始化界面的方法function init() {    ctx.clearRect(0, 0, width, height); //清空畫布    pointerArr = []; //清楚繪制路徑    for (var i = 0; i < arr.length; i++) {        arr[i].state = 0; //清除繪制狀態        drawPointer(i);    }}//繪制九宮格解鎖界面function drawPointer(i) {    ctx.save();    var radius = 0;    if (hastouch) {        radius = width / 12;    } else {        radius = 24;    }    var _fillStyle = "#dd514c";    var _strokeStyle = "#dd514c";    //不同狀態顯示不同顏色    if (arr[i].state == 1) {        _strokeStyle = "#1bd6c5";    }    //繪制原點    ctx.beginPath();    ctx.fillStyle = _fillStyle;    ctx.arc(arr[i].x, arr[i].y, 6, 0, Math.PI * 2, false);    ctx.fill();    ctx.closePath();    //繪制圓圈    ctx.beginPath();    ctx.strokeStyle = _strokeStyle;    ctx.lineWidth = 0.3;    ctx.lineCap = "round";    ctx.lineJoin = "round";    ctx.arc(arr[i].x, arr[i].y, radius, 0, Math.PI * 2, false);    ctx.stroke();    ctx.closePath();    ctx.restore();}//初始化界面init();

繪制連線

繪制連線的方法

var pointerArr = []; //連接線點的坐標數組var startX, startY; //線條起始點var puts = []; //經過的九個點的數組var currentPointer; //當前點是否已經連接var pwd = []; //密碼var confirmPwd = []; //確認密碼var unlockFlag = false; //是否解鎖的標志/** ** 繪制鏈接線的方法,將坐標數組中的點繪制在canvas畫布中 **/function drawLinePointer(x, y, flag) {    ctx.clearRect(0, 0, width, height);    ctx.save();    ctx.beginPath();    ctx.strokeStyle = "#1bd6c5";    ctx.lineWidth = 5;    ctx.lineCap = "round";    ctx.lineJoin = "round";    for (var i = 0; i < pointerArr.length; i++) {        if (i == 0) {            ctx.moveTo(pointerArr[i].x, pointerArr[i].y);        } else {            ctx.lineTo(pointerArr[i].x, pointerArr[i].y);        }    }    ctx.stroke();    ctx.closePath();    ctx.restore();    for (var i = 0; i < arr.length; i++) {        drawPointer(i); //繪制圓圈和原點        if (ctx.isPointInPath(x, y) && currentPointer != i) {            //判斷鼠標點擊是否在圓中            pointerArr.push({                x: arr[i].x,                y: arr[i].y            });            currentPointer = i;            puts.push(i + 1);            startX = arr[i].x;            startY = arr[i].y;            arr[i].state = 1;        }    }    if (flag) {        ctx.save();        ctx.beginPath();        ctx.globalCompositeOperation = "destination-over";        ctx.strokeStyle = "#e2e0e0";        ctx.lineWidth = 5;        ctx.lineCap = "round";        ctx.lineJoin = "round";        ctx.moveTo(startX, startY);        ctx.lineTo(x, y);        ctx.stroke();        ctx.beginPath();        ctx.restore();    }}

綁定事件

連線的過程就是將 3 個 touch(移動端) 事件組合起來獲取當前位置的坐標放入數組中,然后將這些坐標渲染到界面上的過程。

  • touchstart (mousedown) 當手指(鼠標)按下時設置 isMouseDown=true,同時將該點的坐標保存到線條數組中,并將數組中的點繪制出來。
  • touchmove (mousemove) 當 isMouseDown=true 時 將手指(鼠標)移動過程中所有的坐標點都保存到蕭條數組中,并將數組中的點繪制出來。
  • mouseup (mouseup) 當手指(鼠標)松開后設置 isMouseDown=fasle.將數組中的所有點繪制出來,清空 pointerArr 數組,然后比較連接的點的數量如果小于 6(自己設置,一般密碼 6 位以上)給一個密碼長度不夠的提示,清空 puts 數組,重新調用 init 方法初始化界面,如果大于等于 6 則密碼設置成功。
//兼容移動觸摸的事件寫法var hastouch = "ontouchstart" in window ? true : false,    tapstart = hastouch ? "touchstart" : "mousedown",    tapmove = hastouch ? "touchmove" : "mousemove",    tapend = hastouch ? "touchend" : "mouseup";//綁定按下事件lockCnavs.addEventListener(tapstart, function(e) {    isMouseDown = true;    var x1 = hastouch        ? e.targetTouches[0].pageX        : e.clientX - canvas.offsetLeft;    var y1 = hastouch ? e.targetTouches[0].pageY : e.clientY - canvas.offsetTop;    drawLinePointer(x1, y1, true);});//移動時候,將經過的坐標點全部保存起來lockCnavs.addEventListener(tapmove, function(e) {    if (isMouseDown) {        var x1 = hastouch            ? e.targetTouches[0].pageX            : e.clientX - canvas.offsetLeft;        var y1 = hastouch            ? e.targetTouches[0].pageY            : e.clientY - canvas.offsetTop;        drawLinePointer(x1, y1, true);    }});//取消lockCnavs.addEventListener(tapend, function(e) {    drawLinePointer(0, 0, false);    isMouseDown = false;    pointerArr = [];    if (puts.length >= 6) {        alert("你的圖案密碼是: [   " + puts.join("    >   ") + "   ]");        if (unlockFlag) {            //解鎖            unlock();        } else {            //設置解鎖密碼            settingUnlockPwd();        }    } else {        if (puts.length >= 1) {            alert("你的圖案密碼太簡單了~~~");            init();        }    }    puts = [];});

實現解鎖邏輯

通過上面幾步的操作,九宮格解鎖每一次繪圖之后的數據和顯示效果都有了,現在只需要在關鍵地方添加相應邏輯代碼就可以了,這里主要介紹它的實現邏輯就不對代碼做封裝了。

相關代碼

//設置解鎖密碼和解鎖測試function settingUnlockPwd() {    if (pwd.length <= 0) {        pwd = puts;        init();        $("header").text("再次繪制解鎖圖案");    } else if (confirmPwd.length <= 0) {        confirmPwd = puts;    }    console.log(pwd + "  " + confirmPwd);    //筆記兩次密碼是否正確    if (pwd.length > 0 && confirmPwd.length > 0) {        if (compareArr(pwd, confirmPwd)) {            $("header").text("解鎖圖案繪制成功");            init();        } else {            $("header").text("兩次繪制的解鎖圖案不一致");            init();            confirmPwd = [];        }    }}//解鎖function unlock() {    console.log("解鎖密碼:" + puts + "  " + confirmPwd);    if (compareArr(puts, confirmPwd)) {        $("header").text("解鎖成功!頁面跳轉中......");    } else {        $("header").text("解鎖圖案不正確?。?!");        init();    }}$("footer").click(function() {    if ($(this).text() === "解鎖") {        unlockFlag = true;        init();        $("header").text("繪制解鎖圖案");    }});//比較兩個數組(Number)是否相等function compareArr(arr1, arr2) {    return arr1.toString() === arr2.toString();}

后記

本文完整 demo 在線演示地址

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97久久超碰福利国产精品…| 久久综合色影院| 成人激情视频小说免费下载| 久久99久久亚洲国产| 亚洲视频一区二区| 国产精品久久久久9999| 久久好看免费视频| 91在线高清免费观看| 欧美日韩国产限制| 日韩精品中文字幕视频在线| 国产精品久久久久久久久免费看| 久久精品视频在线观看| 国产精品久久久久7777婷婷| 一区二区三区视频免费| 欧美性资源免费| 亚洲无限av看| 狠狠色噜噜狠狠狠狠97| 欧美日韩精品国产| 国产日韩欧美在线看| 九九热在线精品视频| 精品久久久精品| 亚洲精品永久免费| 欧美超级免费视 在线| 深夜福利日韩在线看| 精品久久久久久久久久国产| 欧美天天综合色影久久精品| 国产成人一区二区| 久久精品国产亚洲| 亚洲免费伊人电影在线观看av| 亚洲一区二区三区乱码aⅴ蜜桃女| 久久久99久久精品女同性| 日韩暖暖在线视频| 国产午夜精品理论片a级探花| 九色精品美女在线| 亚洲字幕在线观看| 国产精品丝袜高跟| 亚洲国产高潮在线观看| 91精品国产91久久久久久最新| 国产精品老女人视频| 国产亚洲精品久久久| 91黑丝高跟在线| 日韩成人中文字幕| 亚洲一二在线观看| 亚洲尤物视频网| 国精产品一区一区三区有限在线| 亚洲国产精品高清久久久| 亚洲成人精品在线| 91高潮精品免费porn| 国产精品18久久久久久首页狼| 亚洲天堂2020| 日韩免费观看视频| 欧美一级黑人aaaaaaa做受| 国产精品尤物福利片在线观看| 亚洲free性xxxx护士白浆| 成人激情电影一区二区| 亚洲国产古装精品网站| 日韩亚洲欧美成人| 色综合伊人色综合网站| 国产在线观看91精品一区| 日韩av在线网站| 国产精品一区二区电影| 国产精品国内视频| 精品国产区一区二区三区在线观看| 欧美日韩国产123| 伊人伊成久久人综合网小说| 欧美高清理论片| 自拍偷拍亚洲精品| 国产日韩欧美在线看| 国产精品jvid在线观看蜜臀| 蜜臀久久99精品久久久无需会员| 日产精品久久久一区二区福利| 亚洲精品98久久久久久中文字幕| 亚洲欧洲在线播放| 精品视频中文字幕| 日韩a**中文字幕| 日韩av中文字幕在线免费观看| 91九色在线视频| 久久久爽爽爽美女图片| 91精品久久久久久久久中文字幕| 欧美有码在线观看| 欧美午夜视频在线观看| 欧美在线视频观看| 国产精品成人v| 91久久国产精品| 青青精品视频播放| 国产精品免费网站| 欧美成人午夜剧场免费观看| 欧美第一淫aaasss性| 久久国产精品首页| 国产精品免费观看在线| 国产亚洲激情在线| 精品偷拍各种wc美女嘘嘘| 久久全球大尺度高清视频| www欧美xxxx| 国产精品久久精品| 亚洲女同精品视频| 精品视频www| 久久艹在线视频| 在线看欧美日韩| 国产精品久久久久一区二区| 欧美麻豆久久久久久中文| 欧美日韩成人在线播放| 亚洲大胆美女视频| 色中色综合影院手机版在线观看| 国产亚洲人成a一在线v站| 粉嫩av一区二区三区免费野| 久久最新资源网| 亚洲成人网av| 国产视频在线一区二区| 人九九综合九九宗合| 38少妇精品导航| 成人久久一区二区三区| 欧美野外猛男的大粗鳮| 欧美激情亚洲一区| 91精品国产高清久久久久久91| 尤物九九久久国产精品的特点| 国色天香2019中文字幕在线观看| 日韩av电影手机在线观看| 日本欧美国产在线| 国产91露脸中文字幕在线| 日韩激情av在线播放| 97在线免费观看| 亚洲美女av网站| 精品中文字幕在线| 成人免费午夜电影| 日本久久久久久| 亚洲天堂一区二区三区| 欧美色图在线视频| 97在线日本国产| 在线视频免费一区二区| 日韩欧美黄色动漫| 97精品伊人久久久大香线蕉| 久久韩剧网电视剧| 欧美精品videosex性欧美| 国产亚洲精品美女| 2018国产精品视频| 国产精品va在线播放我和闺蜜| 国产精品 欧美在线| 一区二区三区 在线观看视| 日韩大片免费观看视频播放| 亚洲成人久久网| 久久久噜噜噜久久久| 成人网在线视频| 欧美性视频在线| 国产精品夫妻激情| 欧美日韩精品在线| 91精品久久久久久久久久入口| 国产欧美精品日韩| 日韩欧美亚洲国产一区| 最新的欧美黄色| 日韩中文娱乐网| 色偷偷噜噜噜亚洲男人| 欧美激情成人在线视频| 亚洲欧美在线一区二区| 麻豆精品精华液| 日韩av一卡二卡| 欧美日韩成人在线视频| 欧美激情一区二区三区在线视频观看| 亚洲精选在线观看| 国产精品成人播放| www.亚洲人.com| 国产99久久精品一区二区 夜夜躁日日躁| 日韩av一区在线观看| www.美女亚洲精品|