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

首頁 > 編程 > HTML > 正文

h5使用canvas畫布實現(xiàn)手勢解鎖

2024-08-26 00:21:15
字體:
供稿:網(wǎng)友

前言

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

h5,canvas,畫布,手勢解鎖

原生實現(xiàn)還是其它方式實現(xiàn)?

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

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

原理分析

h5,canvas,畫布,手勢解鎖

手勢解鎖

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

實現(xiàn)步驟

繪制密碼盤

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

var width = $(document).width();var height = $(document).height() - 40; //減去手機狀態(tài)欄的高度//九宮格其實就是九個點,9個點的坐標對象var lockCicle = {    x: 0, //x坐標    y: 0, //y坐標    color: "#999999",    state: "1" //狀態(tài)當前點是否已經(jīng)被鏈接過};var offset = (width - height) / 2; //計算偏移量var arr = []; //九個點的坐標數(shù)組//計算九個點坐標的方法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; //清除繪制狀態(tài)        drawPointer(i);    }}//繪制九宮格解鎖界面function drawPointer(i) {    ctx.save();    var radius = 0;    if (hastouch) {        radius = width / 12;    } else {        radius = 24;    }    var _fillStyle = "#dd514c";    var _strokeStyle = "#dd514c";    //不同狀態(tài)顯示不同顏色    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 = []; //連接線點的坐標數(shù)組var startX, startY; //線條起始點var puts = []; //經(jīng)過的九個點的數(shù)組var currentPointer; //當前點是否已經(jīng)連接var pwd = []; //密碼var confirmPwd = []; //確認密碼var unlockFlag = false; //是否解鎖的標志/** ** 繪制鏈接線的方法,將坐標數(shù)組中的點繪制在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(移動端) 事件組合起來獲取當前位置的坐標放入數(shù)組中,然后將這些坐標渲染到界面上的過程。

  • touchstart (mousedown) 當手指(鼠標)按下時設(shè)置 isMouseDown=true,同時將該點的坐標保存到線條數(shù)組中,并將數(shù)組中的點繪制出來。
  • touchmove (mousemove) 當 isMouseDown=true 時 將手指(鼠標)移動過程中所有的坐標點都保存到蕭條數(shù)組中,并將數(shù)組中的點繪制出來。
  • mouseup (mouseup) 當手指(鼠標)松開后設(shè)置 isMouseDown=fasle.將數(shù)組中的所有點繪制出來,清空 pointerArr 數(shù)組,然后比較連接的點的數(shù)量如果小于 6(自己設(shè)置,一般密碼 6 位以上)給一個密碼長度不夠的提示,清空 puts 數(shù)組,重新調(diào)用 init 方法初始化界面,如果大于等于 6 則密碼設(shè)置成功。
//兼容移動觸摸的事件寫法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);});//移動時候,將經(jīng)過的坐標點全部保存起來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 {            //設(shè)置解鎖密碼            settingUnlockPwd();        }    } else {        if (puts.length >= 1) {            alert("你的圖案密碼太簡單了~~~");            init();        }    }    puts = [];});

實現(xiàn)解鎖邏輯

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

相關(guān)代碼

//設(shè)置解鎖密碼和解鎖測試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("解鎖成功!頁面跳轉(zhuǎn)中......");    } else {        $("header").text("解鎖圖案不正確?。?!");        init();    }}$("footer").click(function() {    if ($(this).text() === "解鎖") {        unlockFlag = true;        init();        $("header").text("繪制解鎖圖案");    }});//比較兩個數(shù)組(Number)是否相等function compareArr(arr1, arr2) {    return arr1.toString() === arr2.toString();}

后記

本文完整 demo 在線演示地址

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。


注:相關(guān)教程知識閱讀請移步到HTML教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
亚洲国产欧美一区二区三区同亚洲| 欧美国产禁国产网站cc| 成人免费网址| 欧美国产一区视频在线观看| 国产精品第五页| 无码日韩精品一区二区| 美女尤物国产一区| 国产二区三区四区| 亚洲专区一二三| 国产激情在线免费观看| 精品三级在线看| 视频一区中文字幕精品| 国产视频每日更新| 亚洲成人精品久久| 国产高清视频在线播放| 资源av在线| 成年女人免费又黄又爽视频| 视频一区二区三区四区五区| 国产精品成熟老女人| 国产成人一区二区三区小说| 成人做爰www免费看视频网站| 国产精品啊v在线| 免费看黄色片的网站| 女仆av观看一区| 国产亚洲欧洲在线| 日本h片在线看| 日本在线观看免费| 91亚洲欧美激情| www日韩tube| 蜜桃av一区| 久久久精品免费网站| 四虎国产精品永久| 久久综合综合久久| 午夜精品福利在线视频| 在线看片你懂得| 久久精品99久久无色码中文字幕| 国产精品探花在线观看| 91精品亚洲| 三级久久三级久久久| 久久久久久久久久久久久久免费看| 好看的黄色网址| 亚洲av无码乱码国产麻豆| 中文在线字幕在线观看| 欧美精品情趣视频| 久久精品国产999大香线蕉| 亚洲欧美激情在线观看| 天堂网在线观看在线观看精品| 亚洲欧美国产高清| 成人一级毛片| 岛国一区二区三区| 深夜免费福利视频| 色综合久久网| 91香蕉视频免费在线观看| 热久久这里只有| 国产精品国三级国产av| 久久精品一二三四| 韩国av电影在线观看| 国产免费一区二区三区视频| 久久久久久久久久婷婷| 亚洲天堂一区在线| www.久久久.com| 亚洲欧美日韩在线不卡| 婷婷五月综合缴情在线视频| 久久精品国产2020观看福利| 91视频青青草| 成人精品动漫| 国产免费一区二区三区最新6| 亚洲一区电影在线观看| 精品人妻一区二区三区浪潮在线| 牛牛国产精品| 日本一级淫片免费放| 欧美精品一区视频| 日本在线播放不卡| www.精品久久| 69堂免费视频| 一区二区三区欧美日韩| 欧美日韩视频在线观看一区二区三区| 国产高清视频免费观看| 麻豆视频在线观看免费网站黄| 久久精品国内一区二区三区| 黑人性受xxxx黑人xyx性爽| 黄色av电影在线播放| 99热精品国产| 精品国内自产拍在线观看视频| 国产sm调教视频| 免费在线看黄色片| 四虎精品永久免费| 亚洲色图欧洲色图婷婷| 日韩av一二区| 婷婷五月精品中文字幕| 精品一区精品二区| 成人影片在线播放| 无限资源日本好片| 国产精品毛片久久久久久久av| 精品黑人一区二区三区在线观看| 日本成在线观看| 日本免费网站| 欧洲一区二区日韩在线视频观看免费| 337p日本欧洲亚洲大胆色噜噜| 粉嫩一区二区三区| 成人亚洲视频在线观看| 欧洲日韩一区二区三区| 超碰在线播放97| 欧美黄色一级生活片| 欧美日韩在线观看首页| 青青艹在线视频| 日日夜夜免费精品| 欧美成熟视频| 日韩激情视频在线| gv天堂gv无码男同在线观看| 第一中文字幕在线| 五月香视频在线观看| 精品免费99久久| 国产午夜精品无码| 在线免费观看日韩欧美| 欧美精品久久久久久久多人混战| 欧洲av无码放荡人妇网站| 色婷婷久久av| 久久亚洲国产精品日日av夜夜| 国产精品日日摸夜夜爽| 天堂俺去俺来也www久久婷婷| 在线观看av资源| h在线视频免费观看完整版| 日本少妇一区| 有码中文亚洲精品| 国产中文字幕一区二区三区| 日本视频一区在线观看| 97精品人人妻人人| 91精品国产自产91精品| 国产精品久久久久久久天堂第1集| 精品一区二区三区在线观看l| 中文在线一区二区三区| 国产黄色大片在线观看| 一区二区亚洲精品国产| www.四虎成人| 99久久国产免费| 亚洲一区成人在线| www.嫩草免费在线观看| 丁香婷婷激情网| 日韩精品一区二区三区外面| 最新国产在线观看| 国产一区二区三区视频在线| 亚洲欧美激情四射在线日| 天天干天天干天天干天天| 色吧亚洲日本| 欧美丰满熟妇xxxxx| 电影网一区二区| 欧美一区二区日韩| 欧美变态凌虐bdsm| 美日韩中文字幕| 国产麻豆一区二区三区精品| 欧美凹凸一区二区三区视频| 这里只有精品在线观看视频| 亚洲最大中文字幕| 视频二区在线观看| 免费观看的黄色网址| 欧美极品少妇videossex| 国产日韩在线视频| 亚洲国产精品91| 深夜在线视频| 国产玉足榨精视频在线观看| 亚欧美无遮挡hd高清在线视频| 日本中文字幕片| 91精品国产自产精品男人的天堂| 天天综合网在线观看| 国产激情精品一区二区三区| 色爱av美腿丝袜综合粉嫩av| 日韩人妻一区二区三区蜜桃视频| 国产校园另类小说区| 国产亚洲成av人片在线观黄桃| 日韩av资源网| 亚洲不卡视频在线观看| 欧美精品a∨在线观看不卡| 亚洲国产第一页| 黄色美女一级片| 麻豆一区一区三区四区| 欧美影院视频| 国产欧洲精品视频| 免费av片在线观看一道本| 在线亚洲欧美视频| 亚洲精品一区二区三区新线路| 亚洲а∨天堂久久精品9966| 一色屋成人免费精品网| 国产精品乱人伦一区二区| 欧美一区二区三区四区五区六区| 在线视频亚洲欧美| 91精品国产综合久久久久久漫画| 性色av一区二区咪爱| 大美女一区二区三区| 成人福利av| 日本猛少妇色xxxxx免费网站| 伊人久久免费视频| 国产精品一区在线观看| 亚洲第一综合网| 国产av不卡一区二区| 一区二区三区日韩精品视频| 激情小说中文字幕| 日韩精品视频中文在线观看| 你懂的免费在线观看视频网站| 美女黄色成人网| 色综合久久综合网欧美综合网| 国产精品羞羞答答xxdd| 嫩草国产精品入口| 宅男噜噜噜66一区二区66| 中文字幕精品—区二区日日骚| 精品免费日韩av| 欧美成人r级一区二区三区| 午放福利视频在线播放| 中文字幕一区二区视频| 91亚洲大成网污www| 特级毛片在线| 国模一区二区| 日韩影视在线观看| 欧美日韩国产高清一区二区| 精品成av人一区二区三区| 99在线免费观看| 中文字幕第88页| 国产成人av片| 2020国产精品视频| 中文字幕欧美日本乱码一线二线| 欧美日韩精品一区二区三区蜜桃| 国产97在线|日韩| 色播亚洲视频在线观看| 国产精品亚洲二区在线观看| 日本一二三四区视频| 国产伦精品一区二区三区免费迷| 在线观看日本www| 污视频在线免费| 不卡福利视频| 日韩电影免费观看在| 一区二区视频网站| 一级日本不卡的影视| 亚洲熟女综合色一区二区三区| 色激情天天射综合网| 欧美日韩不卡中文字幕在线| 蜜臀久久99精品久久久久久宅男| 国产suv精品一区二区四区视频| 不卡影院免费观看| 古典武侠综合av第一页| 经典一区二区三区| 日韩人妻精品中文字幕| 成人免费不卡视频| 97精品久久人人爽人人爽| 中文字幕色呦呦| 欧美特黄a级高清免费大片a级| 欧美亚洲图片小说| 国产成人aaa| 成人直播在线| 97最新国自产拍视频在线完整在线看| 亚洲香蕉伊在人在线观| 欧美一区二区三区黄片| 欧美va亚洲va| 韩国一区二区三区| 国内精品视频免费| 日本xxxx人| h网在线观看| 男人草女人视频| 日本黄色特级片| 欧美xxxx视频| 亚洲涩涩av| 欧在线一二三四区| 韩国成人在线视频| 精品一区在线观看视频| 国产精品福利小视频| 97高清免费视频| 中文字幕制服丝袜在线| 国产精品自在| 欧美制服第一页| 欧洲不卡视频| 午夜婷婷国产麻豆精品| 538在线精品| 天堂中文在线免费观看| 精选一区二区三区四区五区| 在线免费av一区| 伊人久久大香线蕉成人综合网| 好想男人揉我下面好多水| 欧美刺激脚交jootjob| 姝姝窝人体www聚色窝| 性色av无码久久一区二区三区| 8x海外华人永久免费日韩内陆视频| 中国女人内谢69xxxx免费视频| 精品久久久免费视频| 亚洲欧洲第一视频| www.国产精品.com| 欧美性xxxxx极品视频| 国产女主播在线| 91精品国产91| 亚洲人妻一区二区三区| 欧美野外猛男的大粗鳮| 黑人另类精品××××性爽| 亚洲制服欧美中文字幕中文字幕| 青青操在线观看视频| 影音先锋中文字幕在线播放| 亚洲欧美另类日本| 久久伊人一区二区| 亚洲综合自拍| 91久久国产婷婷一区二区| 成人免费av片| 波多野结衣一区二区三区在线| 国产亚洲污的网站| 欧美呦呦网站| 米奇.777.com| 亚洲高清三级视频| 国产精品视频白浆免费视频| 国产日韩欧美一区二区三区| 成人小视频在线| 欧美在线va视频| 伊人成人网在线看| 九色porny丨首页入口在线| 国产一区二区三区成人| 日皮视频在线免费观看| 狠狠精品干练久久久无码中文字幕| 国产成人艳妇aa视频在线| av免费在线不卡| 91久久精品www人人做人人爽| 久草福利在线视频| 色婷婷在线视频观看| 91精品国产91久久久久久| 97视频中文字幕| 日本少妇一区二区三区| 国产精品理论片在线观看| 国内精品麻豆美女在线播放视频| 国产在线观看免费麻豆| 精品国产电影一区| 国产精品边吃奶边做爽| 超碰免费在线公开| 精品国产污污免费网站入口| 天码人妻一区二区三区在线看|