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


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 浮点运算精度问题分析与解决
Mar 26 Javascript
jQuery中prevUntil()方法用法实例
Jan 08 Javascript
JS实现带有3D立体感的银灰色竖排折叠菜单代码
Oct 20 Javascript
JavaScript模版引擎的基本实现方法浅析
Feb 15 Javascript
Angularjs 制作购物车功能实例代码
Sep 14 Javascript
Vue实例简单方法介绍
Jan 20 Javascript
javascript动态创建对象的属性详解
Nov 07 Javascript
vue使用swiper实现中间大两边小的轮播图效果
Nov 24 Javascript
JavaScript计算出两个数的差值
Mar 19 Javascript
js实现时间日期校验
May 26 Javascript
原生JavaScript实现弹幕组件的示例代码
Oct 12 Javascript
vue实现拖拽交换位置
Apr 07 Vue.js
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
咖啡与水的关系
2021/03/03 冲泡冲煮
一首老MP3,致敬WAR3经典
2021/03/08 魔兽争霸
php array_flip() 删除数组重复元素
2009/01/14 PHP
php中通过curl smtp发送邮件
2012/06/05 PHP
分享一个超好用的php header下载函数
2014/01/31 PHP
PHP调用C#开发的dll类库方法
2014/07/28 PHP
php发送短信验证码完成注册功能
2015/11/24 PHP
php实现的错误处理封装类实例
2017/06/20 PHP
JavaScript 给汉字排序实例代码
2008/06/28 Javascript
node.js中的buffer.toJSON方法使用说明
2014/12/14 Javascript
javascript制作2048游戏
2015/03/30 Javascript
jQuery使用animate创建动画用法实例
2015/08/07 Javascript
jquery拖拽排序简单实现方法(效果增强版)
2016/02/16 Javascript
jQuery 遍历map()方法详解
2016/11/04 Javascript
详解Angular 4.x NgTemplateOutlet
2017/05/24 Javascript
详解如何在vue-cli中使用vuex
2018/08/07 Javascript
layui点击导航栏刷新tab页的示例代码
2018/08/14 Javascript
VUE 自定义组件模板的方法详解
2019/08/30 Javascript
ES6常用小技巧总结【去重、交换、合并、反转、迭代、计算等】
2019/12/21 Javascript
js调用网络摄像头的方法
2020/12/05 Javascript
[44:15]国士无双DOTA2 6.82版本详解(上)
2014/09/28 DOTA
[02:01]2018完美盛典-开场舞《双子星》
2018/12/16 DOTA
单链表反转python实现代码示例
2018/02/08 Python
Sanic框架配置操作分析
2018/07/17 Python
python文件操作之批量修改文件后缀名的方法
2018/08/10 Python
Python API 自动化实战详解(纯代码)
2019/06/11 Python
matplotlib 曲线图 和 折线图 plt.plot()实例
2020/04/17 Python
python SOCKET编程基础入门
2021/02/27 Python
详解H5 活动页之移动端 REM 布局适配方法
2017/12/07 HTML / CSS
英国最大的女士服装零售商:Bonmarché
2017/08/17 全球购物
shallow copy和deep copy的区别
2016/05/09 面试题
西游降魔篇观后感
2015/06/15 职场文书
2015年国庆晚会主持词
2015/07/01 职场文书
庆祝教师节新闻稿
2015/07/17 职场文书
深入理解redis中multi与pipeline
2021/06/02 Redis
Fluentd搭建日志收集服务
2022/09/23 Servers