微信小程序?qū)崿F(xiàn)之手勢鎖功能實(shí)例代碼
設(shè)計(jì)思路流程圖
1、全局常量
constructor(page,opts){ // 初始化全局常量數(shù)據(jù) this.page = page; this.width = opts.width || 300; this.height = opts.height || 300; this.canvasId = opts.canvasId || 'lock'; this.type = opts.type || 3; this.cleColor = opts.cleColor || 'rgba(0,136,204,1)'; this.size = this.width / this.type / 2;//坐標(biāo)點(diǎn)之間的半間距 this.R = this.size / 2;//外圓半徑 this.r = this.size / 4;//內(nèi)圓半徑 // 判斷是否在緩存中存在密碼,如果存在,直接進(jìn)行第二步驟:解碼,如果不存在,進(jìn)行初始化,設(shè)置密碼 this.pswObj = wx.getStorageSync('password') ? { step: 2, password: JSON.parse(wx.getStorageSync('password')) } : { step: 0 }; // 啟動(dòng)手勢鎖初始化 this.init(); }
2、全局變量
init(){ const _this = this; // 定義全局變量,標(biāo)記start,手勢鎖的每個(gè)坐標(biāo)的中心點(diǎn)數(shù)組,記錄選中數(shù)組 _this.flag = false; _this.locationArr = []; _this.lastPoint = []; _this.restPoint = []; // 設(shè)置canvas的寬高 _this.page.setData({ width : _this.width, height : _this.height }); this.ctx = wx.createCanvasContext(this.canvasId, this); // 初始化中心坐標(biāo)數(shù)組 this.location(); // 初始化繪制圖形圓 this.drawPo(); // 初始化綁定事件 this.bindEvent(); }
3、初始化坐標(biāo)數(shù)組locationArr 和restPoint
location(){ // 計(jì)算坐標(biāo)的x,y坐標(biāo),同時(shí)記錄當(dāng)前位置代表的數(shù) let count = 0,arr = [],arr0 = []; for(let i = 0; i < this.type; i++){ for(let j = 0 ; j < this.type; j++){ count++; arr.push({ x: this.size * ((j + 1) * 2 - 1),//奇數(shù)個(gè)坐標(biāo)間半間距 y: this.size * ((i + 1) * 2 - 1),//奇數(shù)個(gè)坐標(biāo)間半間距 count: count//每個(gè)坐標(biāo)代表的數(shù) }); arr0.push({ x: this.size * ((j + 1) * 2 - 1),//奇數(shù)個(gè)坐標(biāo)間半間距 y: this.size * ((i + 1) * 2 - 1),//奇數(shù)個(gè)坐標(biāo)間半間距 count: count//每個(gè)坐標(biāo)代表的數(shù) }); } } this.locationArr = arr; this.restPoint = arr0; }
4、繪制手勢鎖矩陣
繪制圓函數(shù)(bool值判斷當(dāng)前繪制的是空心還是實(shí)心)
drawCle(x, y, r, bool){ // 設(shè)置邊框顏色。 bool ? this.ctx.setStrokeStyle(this.cleColor) : this.ctx.setFillStyle(this.cleColor);; // 注意用set // 設(shè)置線條的寬度。 this.ctx.setLineWidth(2); // 注意用set // 開始創(chuàng)建一個(gè)路徑,需要調(diào)用fill或者stroke才會(huì)使用路徑進(jìn)行填充或描邊。 this.ctx.beginPath(); // 畫一條弧線。 this.ctx.arc(x, y, r, 0, Math.PI * 2, true); // 關(guān)閉一個(gè)路徑 this.ctx.closePath(); // 畫出當(dāng)前路徑的邊框。默認(rèn)顏色色為黑色。 bool ? this.ctx.stroke():this.ctx.fill(); // 將之前在繪圖上下文中的描述(路徑、變形、樣式)畫到 canvas 中。 this.ctx.draw(true); }
矩陣?yán)L制
drawPo(){ // 繪制空心圓,繪制之前,清空canvas,防止重復(fù)繪制 this.ctx.clearRect(0, 0, this.width, this.height); this.locationArr.forEach(current => { this.drawCle(current.x, current.y, this.R, true); }); }
5、觸發(fā)move時(shí)線的繪制函數(shù)
drawLine(po) {// 解鎖軌跡 this.ctx.beginPath(); // 線寬 this.ctx.lineWidth = 3; // 起始點(diǎn) this.ctx.moveTo(this.lastPoint[0].x, this.lastPoint[0].y); // 中間轉(zhuǎn)換的點(diǎn) for (var i = 1; i < this.lastPoint.length; i++) { this.ctx.lineTo(this.lastPoint[i].x, this.lastPoint[i].y); } // 正在移動(dòng)選擇的點(diǎn) if (po) { this.ctx.lineTo(po.x, po.y);} this.ctx.stroke(); this.ctx.closePath(); this.ctx.draw(true); }
6、獲取當(dāng)前位置的坐標(biāo)點(diǎn)函數(shù)
getPosition(e) { // 獲取touch點(diǎn)相對于canvas的坐標(biāo) return { x: e.touches[0].x, y: e.touches[0].y }; }
7、觸發(fā)touchstart事件處理
_this.page.onTouchStart = function(e){ let po = _this.getPosition(e);//獲取當(dāng)前準(zhǔn)確坐標(biāo) for (let [key,val] of _this.locationArr.entries()){//循環(huán)對比最近的坐標(biāo) if (Math.abs(val.x - po.x) < _this.r && Math.abs(val.y - po.y) < _this.r){ _this.flag = true;//進(jìn)入判斷,觸發(fā)touchstart事件成功 _this.drawCle(val.x, val.y, _this.r, false);//繪制該點(diǎn)的實(shí)心內(nèi)圓 _this.lastPoint.push(val);//記錄該點(diǎn)坐標(biāo)到lastPoint _this.restPoint.splice(key,1);//刪除記錄數(shù)組restPoint的該點(diǎn)坐標(biāo) break;//找到坐標(biāo),跳出循環(huán) } } }
8、觸發(fā)touchmove事件處理
_this.page.onTouchMove = function (e) { _this.flag && _this.updata(_this.getPosition(e)); }
判斷是否觸發(fā)touchstart,如果觸發(fā),執(zhí)行updata函數(shù)。
更新最后點(diǎn)坐標(biāo)函數(shù)
updata(po){ //清空canvas this.ctx.clearRect(0, 0, this.width, this.height); //重新繪制矩陣 for (let val of this.locationArr) { this.drawCle(val.x, val.y, this.R, true); } //繪制已記錄坐標(biāo)的實(shí)心圓 for (let val of this.lastPoint) { this.drawCle(val.x, val.y, this.r ,false); } //繪制解鎖路線 this.drawLine(po); //找到移動(dòng)中的還未落點(diǎn)的精確坐標(biāo) for (let [key, val] of this.restPoint.entries()) { if (Math.abs(po.x - val.x) < this.r && Math.abs(po.y - val.y) < this.r) { this.drawCle(val.x, val.y, this.r, false); this.lastPoint.push(val); this.restPoint.splice(key, 1); break; } } }
9、觸發(fā)touchend事件處理
_this.page.onTouchEnd = function (e) { if(_this.flag){ _this.flag = false; _this.endData(); _this.checkPassword(_this.lastPoint); setTimeout(function () { _this.reset(); }, 500); } }
通過流程圖,可以更加清楚的認(rèn)識到做一個(gè)功能需要?jiǎng)?chuàng)建的變量和函數(shù),流程步驟更加清楚,當(dāng)然也需要制作的過程進(jìn)行優(yōu)化。建議制作一些大的功能的時(shí)候,如果流程不清楚,最好繪制流程圖,思路清晰,開發(fā)更快,考慮更周全。
總結(jié)
以上所述是小編給大家介紹的微信小程序?qū)崿F(xiàn)之手勢鎖詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
如何在JavaScript中實(shí)現(xiàn)私有屬性的寫類方式(二)
這篇文章主要介紹了如何在JavaScript中實(shí)現(xiàn)私有屬性的寫類方式。需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12javascript獲取網(wǎng)頁各種高寬及位置的方法總結(jié)
下面小編就為大家?guī)硪黄猨avascript獲取網(wǎng)頁各種高寬及位置的方法總結(jié)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07優(yōu)雅的使用javascript遞歸畫一棵結(jié)構(gòu)樹示例代碼
這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅的使用javascript遞歸畫一棵結(jié)構(gòu)樹的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用javascript具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09微信小程序?qū)崿F(xiàn)點(diǎn)擊圖片旋轉(zhuǎn)180度并且彈出下拉列表
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)點(diǎn)擊圖片旋轉(zhuǎn)180度并且彈出下拉列表,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11