手势解锁实例,微信小程序开垦实战教程之手势解锁

By admin in 4858美高梅 on 2019年6月2日

本文实例为大家大快朵颐了微信小程序手势图案锁屏的现实性代码,供我们参照他事他说加以考察,具体内容如下

微信小程序 监听手势滑动切换页面实例详解

手势解锁是app上海高校规模的解锁方式,比较输入密码格局操作起来要有益于广大。下边体现什么遵照微信小程序达成手提式有线电话机解锁。最后兑现效益如下图:

4858美高梅 1

参考

一.应和的xml里写上手势初叶、滑动、停止的监听:

4858美高梅 2

代码:

H5lock

<view class="touch" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" ></view> 

方方面面功用基于canvas完结,首先增加画布组件,并设定样式

这么些手势解锁的demo使用了这么些类型的算法和主逻辑,整合到微信小程序来,修改了无数地点的语法来适配小程序,去掉了window、document等函数,同期也增加了新的体制来解耦分界面包车型大巴操作和第一方库,那么些上面会介绍到。

效果图

2.js:

<!--index.wxml-->
<view class="container">
 <canvas canvas-id="id-gesture-lock" class="gesture-lock" bindtouchstart="onTouchStart"
  bindtouchmove="onTouchMove" bindtouchend="onTouchEnd"></canvas>
</view>


.gesture-lock {
  margin: 100rpx auto;
  width: 300px;
  height: 300px;
  background-color: #ffffff;
}

然则可惜的是,那么些demo也只可以在开垦工具上游玩,到真机上测试的时候,手指一滑动,页面会跟着滚动,手势无法使用。

4858美高梅 3

var touchDot = 0;//触摸时的原点 
var time = 0;// 时间记录,用于滑动时且时间小于1s则执行左右滑动 
var interval = "";// 记录/清理时间记录 
Page({ 
 data: {...} 
   }) 


Page({ 
 data: { 
     ... 
 }, 
 // 触摸开始事件 
 touchStart: function (e) { 
  touchDot = e.touches[0].pageX; // 获取触摸时的原点 
  // 使用js计时器记录时间  
  interval = setInterval(function () { 
   time++; 
  }, 100); 
 }, 
 // 触摸移动事件 
 touchMove: function (e) { 
  var touchMove = e.touches[0].pageX; 
  console.log("touchMove:" + touchMove + " touchDot:" + touchDot + " diff:" + (touchMove - touchDot)); 
  // 向左滑动  
  if (touchMove - touchDot <= -40 && time < 10) { 
   wx.switchTab({ 
    url: '../左滑页面/左滑页面' 
   });  
  } 
  // 向右滑动 
  if (touchMove - touchDot >= 40 && time < 10) { 
   console.log('向右滑动'); 
   wx.switchTab({ 
    url: '../右滑页面/右滑页面' 
   });  
  } 
 }, 
 // 触摸结束事件 
 touchEnd: function (e) { 
  clearInterval(interval); // 清除setInterval 
  time = 0; 
 }, 
. 
. 
. 
}) 

手势解锁落成代码在gesture_lock.js中(完整源码地址见最后)。

上面我们从那些例子中,来深入分析八个能够学习的点。

WXML

谢谢阅读,希望能帮忙到我们,感激我们对本站的援助!

初始化

一、引进第1方库

<view class="container">
  <view class="reset" bindtap="resetPwd">重置密码</view>
  <view class="title">{{title}}</view>
  <canvas canvas-id="canvas" class="canvas" bindtouchend="onTouchEnd"
   bindtouchstart="onTouchStart" bindtouchmove="onTouchMove"></canvas>
</view>

你或者感兴趣的稿子:

  • 微信小程序手势操作之单触摸点与多触摸点
  • 微信小程序开荒教程-手势解锁实例
  • 微信小程序支付实战教程之手势解锁
  • 微信小程序完结手势图案锁屏效率
  constructor(canvasid, context, cb, opt){
    this.touchPoints = [];
    this.checkPoints = [];
    this.canvasid = canvasid;
    this.ctx = context;
    this.width = opt && opt.width || 300; //画布长度
    this.height = opt && opt.height || 300; //画布宽度
    this.cycleNum = opt && opt.cycleNum || 3;
    this.radius = 0; //触摸点半径
    this.isParamOk = false;
    this.marge = this.margeCircle = 25; //触摸点及触摸点和画布边界间隔
    this.initColor = opt && opt.initColor || '#C5C5C3';  
    this.checkColor = opt && opt.checkColor || '#5AA9EC';
    this.errorColor = opt && opt.errorColor || '#e19984';
    this.touchState = "unTouch";
    this.checkParam();
    this.lastCheckPoint = null;
    if (this.isParamOk) {
      // 计算触摸点的半径长度
      this.radius = (this.width - this.marge * 2 - (this.margeCircle * (this.cycleNum - 1))) / (this.cycleNum * 2)
      this.radius = Math.floor(this.radius);
      // 计算每个触摸点的圆心位置
      this.calCircleParams();
    }
    this.onEnd = cb; //滑动手势结束时的回调函数
  }

作者们地点提到的H五lock那一个库,是个大神写的、专给H伍用的八个功用。我们对它进行了一翻修改,把它引进到小程序上来了。

JS

主要安装有个别参数,如canvas的长宽,canvas的context,手势锁的个数(三乘3,
四乘四),手势锁的颜色,手势滑动结束时的回调函数等。并总计动手势锁的半径。

此间研商下怎么把第三方js库引进到小程序来,分以下多少个步骤:

var Locker = class {
 constructor(page,opt){
  var obj = opt || {};

  this.page = page;
  this.width = obj.width || 300;
  this.height = obj.height || 300;
  this.canvasId = obj.id || 'canvas';
  this.cleColor = obj.cleColor || '#CFE6FF';
  this.cleCenterColor = obj.cleCenterColor || '#CFE6FF';

  var chooseType = obj.chooseType || 3;
  // 判断是否缓存有chooseType,有就用缓存,没有就用传入的值
  this.chooseType = Number(wx.getStorageSync('chooseType')) || chooseType;

  this.init();
 }
 init(){
  this.pswObj = wx.getStorageSync('passwordxx') ? {
   step: 2,
   spassword: JSON.parse(wx.getStorageSync('passwordxx'))
  } : {};

  this.makeState();
  // 创建 canvas 绘图上下文(指定 canvasId)
  this.ctx = wx.createCanvasContext(this.canvasId,this);
  this.touchFlag = false;
  this.lastPoint = [];

  // 绘制圆
  this.createCircle();
  // canvas绑定事件
  this.bindEvent();
 }
 makeState() {
  if (this.pswObj.step == 2) {
   this.page.setData({ title:'请解锁'});
  } else if (this.pswObj.step == 1) {
   // pass
  } else {
   // pass
  }
 }
 // 画圆方法
 drawCle(x,y){
  // 设置边框颜色。
  this.ctx.setStrokeStyle(this.cleColor); // 注意用set
  // 设置线条的宽度。
  this.ctx.setLineWidth(2); // 注意用set
  // 开始创建一个路径,需要调用fill或者stroke才会使用路径进行填充或描边。
  this.ctx.beginPath();
  // 画一条弧线。
  this.ctx.arc(x, y, this.r, 0, Math.PI * 2, true);
  // 关闭一个路径
  this.ctx.closePath();
  // 画出当前路径的边框。默认颜色色为黑色。
  this.ctx.stroke();
  // 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。
  this.ctx.draw(true);
 }

 // 计算两点之间的距离的方法
 getDis(a, b) {
  return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
 }

 // 创建解锁点的坐标,根据canvas的大小(默认300px)来平均分配半径
 createCircle() {
  var n = this.chooseType;
  var count = 0;
  // 计算圆半径
  this.r = this.width / (2 + 4 * n);
  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.width, this.height);

  // 绘制所有的圆
  this.arr.forEach(current => {this.drawCle(current.x, current.y);});
 }



 // 设置密码绘制
 getPosition(e) { // 获取touch点相对于canvas的坐标
  var po = {
   x: e.touches[0].x,
   y: e.touches[0].y
  };
  return po;
 }
 precisePosition(po){
  var arr = this.restPoint.filter(current => Math.abs(po.x - current.x) < this.r && Math.abs(po.y - current.y) < this.r);
  return arr[0];
 }
 drawPoint(obj) { // 初始化圆心

  for (var i = 0; i < this.lastPoint.length; i++) {
   this.ctx.setFillStyle(this.cleCenterColor); // 注意用set方法
   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();
   this.ctx.draw(true);
  }
 }
 drawLine(po) {// 解锁轨迹
  this.ctx.beginPath();
  this.ctx.lineWidth = 3;
  this.ctx.moveTo(this.lastPoint[0].x,this.lastPoint[0].y);

  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();
  this.ctx.draw(true);
 }
 pickPoints(fromPt, toPt) {
  var lineLength = this.getDis(fromPt, toPt);
  var dir = toPt.index > fromPt.index ? 1 : -1;

  var len = this.restPoint.length;
  var i = dir === 1 ? 0 : (len - 1);
  var limit = dir === 1 ? len : -1;

  while (i !== limit) {
   var pt = this.restPoint[i];

   if (this.getDis(pt, fromPt) + this.getDis(pt, toPt) === lineLength) {
    this.drawPoint(pt.x, pt.y);
    this.lastPoint.push(pt);
    this.restPoint.splice(i, 1);
    if (limit > 0) {
     i--;
     limit--;
    }
   }

   i += dir;
  }
 }
 update(po) {// 核心变换方法在touchmove时候调用
  this.ctx.clearRect(0, 0, this.width, this.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++) {
   var pt = this.restPoint[i];

   if (Math.abs(po.x - pt.x) < this.r && Math.abs(po.y - pt.y) < this.r) {
    this.drawPoint(pt.x, pt.y);
    this.pickPoints(this.lastPoint[this.lastPoint.length - 1], pt);
    break;
   }
  }
 }
 checkPass(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;
 }
 storePass(psw) {// touchend结束之后对密码和状态的处理
  if (this.pswObj.step == 1) {
   if (this.checkPass(this.pswObj.fpassword, psw)) {
    this.pswObj.step = 2;
    this.pswObj.spassword = psw;

    this.page.setData({title:'密码保存成功'});

    this.drawStatusPoint('#2CFF26');
    wx.setStorageSync('passwordxx', JSON.stringify(this.pswObj.spassword));
    wx.setStorageSync('chooseType', this.chooseType);
   } else {
    this.page.setData({ title: '两次不一致,重新输入' });
    this.drawStatusPoint('red');
    delete this.pswObj.step;
   }
  } else if (this.pswObj.step == 2) {
   if (this.checkPass(this.pswObj.spassword, psw)) {
    this.page.setData({ title: '解锁成功' });
    this.drawStatusPoint('#2CFF26');
   } else {
    this.drawStatusPoint('red');
    this.page.setData({ title: '解锁失败' });
   }
  } else {
   this.pswObj.step = 1;
   this.pswObj.fpassword = psw;
   this.page.setData({ title: '再次输入' });
  }
 }
 drawStatusPoint(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();
   this.ctx.draw(true);
  }
 }

 updatePassword() {
  wx.removeStorageSync('passwordxx');
  wx.removeStorageSync('chooseType');
  this.pswObj = {};
  this.page.setData({ title: '绘制解锁图案' });
  this.reset();
 }
 reset() {
  this.makeState();
  this.createCircle();
 }
 bindEvent(){
  var self = this;
  this.page.onTouchStart = function(e){
   var po = self.getPosition(e);
   self.lastPoint = [];
   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;
    }
   }
  }

  this.page.onTouchMove = function(e){
   if (self.touchFlag) {
    self.update(self.getPosition(e));
   }
  }

  this.page.onTouchEnd = function(e){
   if (self.touchFlag) {
    self.touchFlag = false;
    self.storePass(self.lastPoint);
    setTimeout(function () {
     self.reset();
    }, 300);
   }
  }
 }
}
module.exports = Locker;

算算每一个手势锁的圆心地点

手势解锁实例,微信小程序开垦实战教程之手势解锁。(1)模块化

DEMO下载.rar)

  calCircleParams() {
    let n = this.cycleNum;
    let count = 0;
    for (let i = 0; i < n; i++) {
      for (let j = 0; j < n; j++){
        count++;
        let touchPoint = {
          x: this.marge + i * (this.radius * 2 + this.margeCircle) + this.radius,
          y: this.marge + j * (this.radius * 2 + this.margeCircle) + this.radius,
          index: count,
          check: "uncheck",
        }
        this.touchPoints.push(touchPoint)
      }
    }
  }

小程序代码中,只好通过module.exports来导出的模块技巧被引述,所以率先步,大家要对代码进行第三个改换,做exports导出:

以上正是本文的全体内容,希望对大家的上学抱有协理,也盼望我们多多支持脚本之家。

绘图手势锁

module.exports = {
...
}
如果要在被引入的时候,执行一些操作,可以用以下两种方式:
//// mylib.js
module.exports = (function() {
// 这里写上你要执行的代码
…
return xxx; //返回你要导出的方法,如果多个就写成一个map
})();
…
//// 其它文件中这么引用和执行:
let MyLib = require('mylib.js');
let lib = Mylib();
lib.xxx(); // 执行
或es6中的class:
//// mylib.js
module.exports = class {
constructor() { // 
// 这里写上你要执行的代码
}
// 其它方法
xxx() { 
...
}
}
…
//// 其它文件中这么引用和执行:
let MyLib = require('mylib.js');
let lib = new Mylib(); // 用new来生成类的对象
lib.xxx(); // 执行

你也许感兴趣的篇章:

  • 微信小程序
    监听手势滑动切换页面实例详解
  • 微信小程序手势操作之单触摸点与多触摸点
  • 微信小程序开拓教程-手势解锁实例
  • 微信小程序支付实战教程之手势解锁
   for (let i = 0; i < this.touchPoints.length; i++){
      this.drawCircle(this.touchPoints[i].x, this.touchPoints[i].y, this.radius, this.initColor)
   }
   this.ctx.draw(true);

(二)对第三方库中的一些函数实行更换

接下去正是识别用户的滑动行为,判定用户划过了怎么圆圈,进而识别出用户的手势。

小程序不帮忙以下多少个函数或api:

在touchstart和touchmove事件中检验触发并更新画布

window
document
frames
self
location
navigator
localStorage
history
caches
screen
alert
confirm
4858美高梅,prompt
XMLHttpRequest
WebSocket

  onTouchStart(e) {
    // 不识别多点触控
    if (e.touches.length > 1){
      this.touchState = "unTouch";
      return;
    }
    this.touchState = "startTouch";
    this.checkTouch(e);
    let point = {x:e.touches[0].x, y:e.touches[0].y};
    this.drawCanvas(this.checkColor, point);
  }

  onTouchMove(e) {
    if (e.touchState === "unTouch") {
      return;
    }
    if (e.touches.length > 1){
      this.touchState = "unTouch";
      return;
    }
    this.checkTouch(e);
    let point = {x:e.touches[0].x, y:e.touches[0].y};
    this.drawCanvas(this.checkColor, point);
  }

跟以上相关的代码二个个寻觅出来,并想艺术替换掉。

检查测试用户是不是划过有些圈子

最普及的貌似是document操作,第3方库注重是用它来引用dom,并对它进行安装或涂改。这些能够通过上边第一点会讲的解耦本领来都行地绕过。别的的就靠开垦者本身去想了,这里不能够壹1列出装有的气象。

  checkTouch(e) {
    for (let i = 0; i < this.touchPoints.length; i++){
      let point = this.touchPoints[i];
      if (isPointInCycle(e.touches[0].x, e.touches[0].y, point.x, point.y, this.radius)) {
        if (point.check === 'uncheck') {
          this.checkPoints.push(point);
          this.lastCheckPoint = point;
        }
        point.check = "check"
        return;
      }
    }
  }

本文的demo用的是class的办法来改动了第一方库。

履新画布

贰、一种解耦的章程

   drawCanvas(color, point) {
    //每次更新之前先清空画布
    this.ctx.clearRect(0, 0, this.width, this.height);
    //使用不同颜色和形式绘制已触发和未触发的锁
    for (let i = 0; i < this.touchPoints.length; i++){
      let point = this.touchPoints[i];
      if (point.check === "check") {
        this.drawCircle(point.x, point.y, this.radius, color);
        this.drawCircleCentre(point.x, point.y, color);
      }
      else {
        this.drawCircle(this.touchPoints[i].x, this.touchPoints[i].y, this.radius, this.initColor)
      }
    }
    //绘制已识别锁之间的线段
    if (this.checkPoints.length > 1) {
       let lastPoint = this.checkPoints[0];
       for (let i = 1; i < this.checkPoints.length; i++) {
         this.drawLine(lastPoint, this.checkPoints[i], color);
         lastPoint = this.checkPoints[i];
       }
    }
    //绘制最后一个识别锁和当前触摸点之间的线段
    if (this.lastCheckPoint && point) {
      this.drawLine(this.lastCheckPoint, point, color);
    }
    this.ctx.draw(true);
  }

在小程序支付的时候,假若多个页面包车型的士js写得太长,以致越过了上千行,那您将在酌量把这一个文件分拆成多少个。也许您写的逻辑代码,能够多少个页面共用,那么你也是要把代码从那一个页面包车型客车js里拆出来的。

当用户滑动截止时调用回调函数并传递识别出的手势

这里就引出了贰个相比较通晓的主题素材:在别的文件中,要修改页面上的多寡,又不可能耦合性太大,因为您的这段逻辑代码,在页面A中会引用到,在页面B中也会引用到,那样总不可能把setData操作放到那几个集体的公文里吗。

  onTouchEnd(e) {
    typeof this.onEnd === 'function' && this.onEnd(this.checkPoints, false);
  }

  onTouchCancel(e) {
    typeof this.onEnd === 'function' && this.onEnd(this.checkPoints, true);
  }

那有何样格局能够解耦呢?

复位和显示手势错误

那个时候,大概你会想到日常页面开拓时,用到的trigger机制,可惜这几个只可以在dom上绑定。也也许你用过
那些库,通过状态机的变迁来触发有些特定的操作,这些点子足够抢眼,没接触过这一个库的开垦者,建议学习一下。

 

只是大家还没有供给再引进一个库,这里,大家来写个大致的。轻巧到只有几行代码。

  gestureError() {
    this.drawCanvas(this.errorColor)
  }

  reset() {
    for (let i = 0; i < this.touchPoints.length; i++) {
      this.touchPoints[i].check = 'uncheck';
    }
    this.checkPoints = [];
    this.lastCheckPoint = null;
    this.drawCanvas(this.initColor);
  }

代码在这里:

何以调用

module.exports = function(app) {
app && (app.trigger = function(eventType, data) {
var pages = getCurrentPages(),
curPage = pages[pages.length-1],
methodName = 'on' + eventType.charAt(0).toUpperCase() + eventType.substr(1),
callback = curPage[methodName];
callback && callback.call(curPage, data);
});
};

在onload方法中开创lock对象并在用户触摸事件中调用相应措施

哪些使用那几个库?剖判一下大致的进度,其实非常轻松,正是给app增添三个trigger方法,当它被调用的时候,去搜寻当前页面是或不是在onXXX方法,有的话就调用。这几个办法名,是透过eventType那个参数变形而成的,如app.trigger(‘textChange’)
,则这里会去搜索页面中是或不是有onTextChange方法。所以实际这一个解耦方法,本质上,是概念了1种规范。

 onLoad: function () {
  var s = this;
  this.lock = new Lock("id-gesture-lock", wx.createCanvasContext("id-gesture-lock"), function(checkPoints, isCancel) {
   console.log('over');
   s.lock.gestureError();
   setTimeout(function() {
    s.lock.reset();
   }, 1000);
  }, {width:300, height:300})
  this.lock.drawGestureLock();
  console.log('onLoad')
  var that = this
  //调用应用实例的方法获取全局数据
  app.getUserInfo(function(userInfo){
   //更新数据
   that.setData({
    userInfo:userInfo
   })
   that.update()
  })
 },
 onTouchStart: function (e) {
  this.lock.onTouchStart(e);
 },
 onTouchMove: function (e) {
  this.lock.onTouchMove(e);
 },
 onTouchEnd: function (e) {
  this.lock.onTouchEnd(e);
 }

首页在app.js里引入,并在onLaunch里调用:

源码地址:源码下载

var event = require('lib/event.js');
App({
onLaunch: function () {
event(this); // 在onLaunch里调用,传入的this就是app本身
},
globalData:{
}
});

以上正是本文的全体内容,希望对我们的读书抱有支持,也期待大家多多帮助脚本之家。

然后在共用的抽离出来的公文中,在急需用到setData的地点,写成如下情势:

你或者感兴趣的篇章:

  • 微信小程序
    监听手势滑动切换页面实例详解
  • 微信小程序手势操作之单触摸点与多触摸点
  • 微信小程序支付实战教程之手势解锁
  • 微信小程序完结手势图案锁屏功用
app.trigger('titleChanged', '请解锁');

紧接着在页面包车型地铁js代码里,增多对这一个trigger的响应:

Page({
…
onTitleChanged: function(newTitle) { // 文字变化的事件,自定义
this.setData({
title: newTitle
});
}
...
});

那三步做完就ok了。

如上所述是小编给我们介绍的微信小程序支付实战教程之手势解锁,希望对大家持有协理,尽管大家有其余疑问请给自家留言,小编会及时还原我们的。在此也特别谢谢大家对剧本之家网站的帮衬!

您或者感兴趣的篇章:

  • 微信小程序
    监听手势滑动切换页面实例详解
  • 微信小程序手势操作之单触摸点与多触摸点
  • 微信小程序开垦教程-手势解锁实例
  • 微信小程序完成手势图案锁屏功用

发表评论

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

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有