An app project I recently worked on used apicloud to achieve cross-platform development. Now I need to add a gesture (nine-square grid) unlocking function to this app. apicloud already has some third-party natively implemented gesture unlocking plug-ins, because it is native and has better performance. Well, it is more convenient to call them, but their styles cannot be modified, so I plan to implement this function myself. This article will organize and share the implementation process. I hope those who need it can understand it. The shared code only implements the most basic 设置密码功能
, 解锁功能
, 比较密码
functions, etc. Some advanced functions such as: cannot limit the maximum number of times a point can be passed, and limit the length of the password set by the user.
Native implementation or other methods?
1. Use the corresponding platforms of android and ios to write the gesture unlock plug-in through native code. The experience is good, but the development cycle is long, the compatibility issues of each platform need to be dealt with, and the APICloud platform plug-in writing method needs to be learned. (give up)
2. Use html5 canvas to implement. The development cycle is short, there is no need to deal with compatibility issues too much, and the experience is good. (choose)
Principle analysis Gesture unlockUse your fingers to connect nine points on the screen in sequence to form a pattern, so it is called pattern unlocking. As shown in the picture above, each unlocking circle is actually followed by a number. What is compared each time is not the pattern drawn by the user, but the password string composed of the numbers under the circles that are connected in series every time the finger passes through the pattern. In essence, we The comparison is still the string password, but from the user's perspective, it is a drawn pattern. The memory of patterns is much stronger than strings of numbers.
Implementation steps draw cipher diskThe drawing of the password disk is relatively simple. The only thing you need to pay attention to is that you need to use dynamic calculation to make the positive pattern surrounded by nine points always in the middle of the screen. On mobile phones, you also need to subtract the height of the status bar.
var width = $(document).width();var height = $(document).height() - 40; //Subtract the height of the mobile phone status bar//The nine-square grid is actually nine points, a coordinate object of 9 points var lockCicle = { x: 0, //x coordinate y: 0, //y coordinate color: #999999, state: 1 //status whether the current point has been linked}; var offset = (width - height) / 2; //Calculate offset var arr = []; //Coordinate array of nine points //Method to calculate coordinates of nine points for (var i = 1; i <= 3; i++) { //Each row for (var j = 1; j <= 3; j++) { //Each var in each row lockCicle = {}; //Horizontal screen if (offset > 0) { lockCicle.x = (height / 4) * j + Math.abs(offset); lockCicle.y = (height / 4) * i; lockCicle.state = 0; //Vertical screen} else { lockCicle.x = (width / 4) * j; lockCicle.y = (width / 4) * i + Math.abs(offset); lockCicle.state = 0; } arr.push(lockCicle); }}//Method function to initialize the interface init() { ctx.clearRect(0, 0, width, height); //Clear the canvas pointerArr = []; //Clear the drawing path for (var i = 0; i < arr.length; i++) { arr[i ].state = 0; //Clear the drawing state drawPointer(i); }}//Draw the nine-square unlock interface function drawPointer(i) { ctx.save(); var radius = 0; if (hastouch) { radius = width / 12; } else { radius = 24; } var _fillStyle = #dd514c; var _strokeStyle = #dd514c; //Different states display different colors if (arr[i].state == 1) { _strokeStyle = #1bd6c5; } //Draw the origin ctx.beginPath(); ctx.fillStyle = _fillStyle; ctx.arc(arr[i].x, arr[i].y, 6, 0, Math.PI * 2, false); ctx.fill(); ctx.closePath(); //Draw circle 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();}//Initialization interface init();Draw a connection How to draw a connection
var pointerArr = []; //Coordinate array of connecting line points var startX, startY; //Starting point of the line var puts = []; //Array of nine passed points var currentPointer; //Whether the current point has been connected var pwd = []; //Password var confirmPwd = []; //Confirm password var unlockFlag = false; //Flag whether to unlock/** ** Method to draw link lines, draw points in the coordinate array on the canvas in**/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); //Draw the circle and origin if (ctx.isPointInPath(x, y) && currentPointer != i) { //Determine whether the mouse click is in the circle 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(); }}Binding event
The process of connecting is to combine three touch (mobile terminal) events to obtain the coordinates of the current position and put them into an array, and then render these coordinates to the interface.
//Event writing compatible with mobile touch var hastouch = ontouchstart in window ? true : false, tapstart = hastouch ? touchstart : mousedown, tapmove = hastouch ? touchmove : mousemove, tapend = hastouch ? touchend : mouseup; //Bind press event 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);}) ;//When moving, save all the coordinate points passed by 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); }});//Cancel lockCnavs.addEventListener(tapend, function(e) { drawLinePointer(0, 0, false); isMouseDown = false; pointerArr = []; if (puts.length >= 6) { alert(Your pattern password is: [ + puts.join( > ) + ]); if (unlockFlag) { //Unlock unlock(); } else { //Set the unlock password settingUnlockPwd(); } } else { if (puts.length >= 1) { alert(Your pattern password is too simple~~~); init(); } } puts = [];});Implement unlocking logic
Through the above steps, the data and display effects after each drawing of Jiugongge are unlocked. Now you only need to add the corresponding logic code in key places. Here we mainly introduce its implementation logic without encapsulating the code.
Related code
//Set the unlock password and unlock test function settingUnlockPwd() { if (pwd.length <= 0) { pwd = puts; init(); $(header).text(draw the unlock pattern again); } else if (confirmPwd. length <= 0) { confirmPwd = puts; } console.log(pwd + + confirmPwd); //Note whether the password twice is correct if (pwd.length > 0 && confirmPwd.length > 0) { if (compareArr(pwd, confirmPwd)) { $(header).text(Unlocking pattern drawn successfully); init(); } else { $(header).text(Unlocking pattern drawn twice) inconsistent); init(); confirmPwd = []; } }}//Unlock function unlock() { console.log(Unlock password: + puts + + confirmPwd); if (compareArr(puts, confirmPwd)) { $(header).text(Unlocking successful! Page jumping...); } else { $(header).text(Unlocking pattern is incorrect!!!); init(); }}$(footer).click(function() { if ($(this).text() === unlock) { unlockFlag = true; init(); $(header).text(draw unlock pattern); }});//Compare two arrays (Number) for equality function compareArr(arr1, arr2) { return arr1.toString() === arr2.toString();}
postscript
The complete demo online demonstration address of this article
The above is the entire content of this article. I hope it will be helpful to everyone’s study. I also hope everyone will support VeVb Wulin Network.