微信小程序开发教程-手势解锁实例


Posted in Javascript onJanuary 06, 2017

手势解锁是app上常见的解锁方式,相比输入密码方式操作起来要方便许多。下面展示如何基于微信小程序实现手机解锁。最终实现效果如下图:

微信小程序开发教程-手势解锁实例

整个功能基于canvas实现,首先添加画布组件,并设定样式

<!--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;
}

手势解锁实现代码在gesture_lock.js中(完整源码地址见末尾)。

初始化

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; //滑动手势结束时的回调函数
  }

主要设置一些参数,如canvas的长宽,canvas的context,手势锁的个数(3乘3, 4乘4),手势锁的颜色,手势滑动结束时的回调函数等。并计算出手势锁的半径。

计算每个手势锁的圆心位置

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)
      }
    }
  }

绘制手势锁

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);

接下来就是识别用户的滑动行为,判断用户划过了哪些圆圈,进而识别出用户的手势。

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

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);
  }

检测用户是否划过某个圆圈

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;
      }
    }
  }

更新画布

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);
  }

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

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

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

重置和显示手势错误

 

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);
  }

如何调用

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

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);
 }

源码地址:源码下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript Event学习第六章 事件的访问
Feb 07 Javascript
javascript 程序库的比较(一)之DOM功能
Apr 07 Javascript
用表格输出1-1000之间的数字实现代码(附特效)
Apr 21 Javascript
jquery中添加属性和删除属性
Jun 03 Javascript
学习JavaScript设计模式之单例模式
Jan 19 Javascript
jquery获取img的src值的简单实例
May 17 Javascript
JavaScript数据存储 Cookie篇
Jul 02 Javascript
ionic实现可滑动的tab选项卡切换效果
Apr 15 Javascript
详解springmvc 接收json对象的两种方式
Dec 06 Javascript
vue获取当前点击的元素并传值的实例
Mar 09 Javascript
JS实现图片拖拽交换效果
Nov 30 Javascript
基于vue和websocket的多人在线聊天室
Feb 01 Javascript
jQuery ajax的功能实现方法详解
Jan 06 #Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
Jan 06 #Javascript
Jqprint实现页面打印
Jan 06 #Javascript
JS使用正则截取两个字符串之间的字符串实现方法详解
Jan 06 #Javascript
jQuery EasyUi 验证功能实例解析
Jan 06 #Javascript
jQuery编写网页版2048小游戏
Jan 06 #Javascript
利用JQuery实现datatables插件的增加和删除行功能
Jan 06 #Javascript
You might like
用mysql_fetch_array()获取当前行数据的方法详解
2013/06/05 PHP
PHP错误提示的关闭方法详解
2013/06/23 PHP
laravel 中如何使用ajax和vue总结
2017/08/16 PHP
深入理解 PHP7 中全新的 zval 容器和引用计数机制
2018/10/15 PHP
PHP5中使用mysqli的prepare操作数据库的介绍
2019/03/18 PHP
使用composer安装使用thinkphp6.0框架问题【视频教程】
2019/10/01 PHP
JavaScript语法着色引擎(demo及打包文件下载)
2007/06/13 Javascript
javascript中的有名函数和无名函数
2007/10/17 Javascript
JQuery 国际象棋棋盘 实现代码
2009/06/26 Javascript
JavaScript 创建对象
2009/07/17 Javascript
从JQuery源码分析JavaScript函数的apply方法与call方法
2014/09/25 Javascript
AngularJS初始化过程分析(引导程序)
2014/12/06 Javascript
JS随机调用指定函数的方法
2015/07/01 Javascript
JQuery Ajax WebService传递参数的简单实例
2016/11/02 Javascript
Javascript highcharts 饼图显示数量和百分比实例代码
2016/12/06 Javascript
jQuery EasyUI 组件加上“清除”功能实例详解
2017/04/11 jQuery
JavaScript通过filereader接口读取文件
2017/05/10 Javascript
JS 60秒后重新发送验证码的实例讲解
2017/07/26 Javascript
Javascript中 toFixed四舍六入方法
2017/08/21 Javascript
jQuery Datatable 多个查询条件自定义提交事件(推荐)
2017/08/24 jQuery
JavaScript undefined及null区别实例解析
2020/07/21 Javascript
JS继承实现方法及优缺点详解
2020/09/02 Javascript
vue+axios 拦截器实现统一token的案例
2020/09/11 Javascript
python设置检查点简单实现代码
2014/07/01 Python
python实现图片处理和特征提取详解
2017/11/13 Python
python smtplib发送带附件邮件小程序
2018/05/22 Python
Python函数装饰器原理与用法详解
2019/08/16 Python
Python之Django自动实现html代码(下拉框,数据选择)
2020/03/13 Python
公认8个效率最高的爬虫框架
2020/07/28 Python
python openssl模块安装及用法
2020/12/06 Python
python 基于PYMYSQL使用MYSQL数据库
2020/12/24 Python
年度考核自我鉴定
2014/02/02 职场文书
2014年银行年终工作总结
2014/12/19 职场文书
银行文明优质服务培训心得体会
2016/01/09 职场文书
2016学习全国教书育人楷模先进事迹心得体会
2016/01/21 职场文书
Python自动化测试PO模型封装过程详解
2021/06/22 Python