微信小程序实现一个手势图案锁组件

在这里插入图片描述

说在前面

🎈现在大部分的人都喜欢使用手势图案锁来作为手机的锁屏,之前我也写过一篇使用vue封装的手势图案锁组件,想了解的可以戳这里->《vue封装一个图案手势锁组件》。那么怎么在微信小程序中实现这种手势锁屏的效果的呢?接下来让我们一起来实现一个微信小程序中可以使用的手势锁屏组件吧!

组件设计

我们主要从页面展示效果和交互效果来进行具体分析:

1、页面效果

1.1 九宫格圆点排列

使用flex布局和flex-wrap效果,使9个圆点可以均匀排列。

  • wxml
<view
    id="{{JAppsLockId + 'lock'}}"
    class="j-apps-lock"
>
    <view class="j-apps-lock-cells">
        <view
            class="j-apps-lock-cell"
            wx:for="{{size * size}}"
            wx:key="index"
            data-id="{{index}}"
            style="border:{{showBorder[index] ? '1px solid gray' : '1px solid transparent'}}"
        >
            <view
                id="{{'point-' + index}}"
                class="j-apps-lock-point"
                data-id="{{index}}"
            ></view>
        </view>
    </view>
</view>
  • wxss
.j-apps-lock {
  position: relative;
  margin: auto;
}
.j-apps-lock-cells {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}
.j-apps-lock-cell {
  display: flex;
  border-radius: 50%;
  justify-content: center;
  width: 26vw;
  height: 26vw;
  margin-top: 2vw;
}
.j-apps-lock-point {
  width: 40%;
  height: 40%;
  justify-content: center;
  background-color: rgb(187, 183, 183);
  display: flex;
  margin: auto;
  border-radius: 50%;
  position: relative;
}
1.2 划动选中圈圈效果

只需要动态判断当前圈圈是否被选中,动态修改style属性即可: border:{{showBorder[index] ? '1px solid gray' : '1px solid transparent'}}

<view
    class="j-apps-lock-cell"
    wx:for="{{size * size}}"
    wx:key="index"
    data-id="{{index}}"
    style="border:{{showBorder[index] ? '1px solid gray' : '1px solid transparent'}}"
>
...
</view>

2、交互效果

2.1 监听触屏划过圆点

我们可以对整个组件界面进行一个触屏监听,判断坐标是否经过某一个圆点的坐标,如果是,可以将当前圆点标记为选中状态。

  • wxml
<view
    id="j-apps-lock-body"
    class="j-apps-lock-body"
    bindtouchstart="mousedown"
    bindtouchmove="mouseover"
    bindtouchend="mouseup"
>
...
</view>
  • js
mousedown(e){
  this.clearPoint();
  if(this.data.points.length == 0) this.getPoints();
},
mouseover(e){
  let points = this.data.points;
  let x = e.touches[0].pageX;
  let y = e.touches[0].pageY;
  let id = '';
  let showBorder = this.data.showBorder;
  for(let i = 0; i < points.length; i++){
    const p = points[i];
    if(x >= p.left && x <= p.right && y <= p.bottom && y >= p.top){
      id = p.dataset.id;
      showBorder[i] = true;
      break;
    }
  }
  let chooseList = this.data.chooseList;
  if(isNaN(parseInt(id)) || chooseList.includes(id)) return;
  chooseList.push(id);
  this.setData({
    chooseList:chooseList,
    showBorder:showBorder
  })
},
2.2 动作结束返回动作轨迹

在手指离开手机屏幕,及触屏事件结束触发mouseup事件的时候,将选中的圈圈坐标顺序传递给父组件,这里我对圈圈的坐标定义如下,大家也可以根据实际情况自己定义:
在这里插入图片描述

mouseup(){
  this.triggerEvent("getPassword", {chooseList:this.data.chooseList});
},

在这里插入图片描述

所以上图的图案滑动轨迹返回的点集数组应该为:

    [1,2,3,6,9,8,7,4,5]

核心代码详解

1、微信小程序获取dom实例对象

在进行点坐标判断的时候,我们需要获取到每一个点的坐标范围,但是在微信小程序中我们不能直接同document.getElementbyId去获取到我们需要的实例对象,那么我们该怎么获取到需要的对象,并得到其相应的坐标范围呢?

1.1 wx.createSelectorQuery()

我们需要先了解一下wx.createSelectorQuery()这个api

  • 功能

返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替。

通过查阅官方文档,我们发现可以通过wx.createSelectorQuery()来获取到页面上的实例对象,这里我们是在小程序组件中使用,所以我们应该使用this.createSelectorQuery()来获取。

getPoints(){
  const query = this.createSelectorQuery();
  let id = '.j-apps-lock-point'
  query.selectAll(id).boundingClientRect((res)=>{
    this.setData({
      points:res
    })
  }).exec()
},

2、判断是否是否划过点位

在这里插入图片描述

前面我们获取的点位的dom实例在这里就可以派上用场了,微信小程序返回的实例对象中会包含这几个属性:

  • left:实例对象最左端坐标
  • right:实例对象最右端坐标
  • top:实例对象最顶端坐标
  • bottom:实例对象最底端坐标
    这里我们有两个方法来判断:
2.1 正方形区域判断

我们可以直接根据实例对象的四个端点坐标来进行一个正方形的大致位置匹配,这样得出来的结果会有少许误差,但也不会有很大的影响:x >= p.left && x <= p.right && y <= p.bottom && y >= p.top

mouseover(e){
  //前面获取的圈圈实例对象集合
  let points = this.data.points;
  //当前触屏坐标
  let x = e.touches[0].pageX;
  let y = e.touches[0].pageY;
  let id = '';
  let showBorder = this.data.showBorder;
  //判断是否划过某一个圈圈
  for(let i = 0; i < points.length; i++){
    const p = points[i];
    if(x >= p.left && x <= p.right && y <= p.bottom && y >= p.top){
      id = p.dataset.id;
      showBorder[i] = true;
      break;
    }
  }
  //记录圈圈选中状态
  let chooseList = this.data.chooseList;
  if(isNaN(parseInt(id)) || chooseList.includes(id)) return;
  chooseList.push(id);
  this.setData({
    chooseList:chooseList,
    showBorder:showBorder
  })
},
2.2 圆形区域判断

我们也可以根据点实例对象的端点得出其圆的方程,我们只需要将坐标代入方程判断是否位于圆内即可:
(x1-x)^2 + (y1-y)^2 <= r^2
所以我们需要计算出圈圈的圆心坐标和半径即可:

const r = (p.right - p.left) / 2;
const x1 = (p.left + p.right) / 2;
const y1 = (p.top + p.bottom) / 2;
mouseover(e){
  let points = this.data.points;
  let x = e.touches[0].pageX;
  let y = e.touches[0].pageY;
  let id = '';
  let showBorder = this.data.showBorder;
  for(let i = 0; i < points.length; i++){
    const p = points[i];
    const r = (p.right - p.left) / 2;
    const x1 = (p.left + p.right) / 2;
    const y1 = (p.top + p.bottom) / 2;
    if(Math.pow(x1 - x,2) + Math.pow(y1 - y,2) <= Math.pow(r,2)){
      id = p.dataset.id;
      showBorder[i] = true;
      break;
    }
  }
  let chooseList = this.data.chooseList;
  if(isNaN(parseInt(id)) || chooseList.includes(id)) return;
  chooseList.push(id);
  this.setData({
    chooseList:chooseList,
    showBorder:showBorder
  })
},

源码地址

该组件是我在自己的一个开源项目中使用到的,源码可以到该项目查看具体代码,地址如下:
微信小程序手势图案锁组件源码

具体位置如下

在这里插入图片描述

往期精彩

vue封装一个图案手势锁组件

vue封装一个弹幕组件

为了学(mo)习(yu),我竟开发了这样一个插件

程序员的浪漫之——情侣日常小程序

JavaScript双向链表实现LRU缓存算法

JavaScript双向链表实现LFU缓存算法

JavaScript实现前缀树

vue简单实现词云图组件

vue + echarts实现中国地图省份下钻联动

使用学过的算法做个游戏很酷的好吗

说在后面

🎉这里是JYeontu,喜欢算法,GDCPC打过卡;热爱羽毛球,大运会打过酱油。毕业一年,两年前端开发经验,目前担任H5前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JYeontu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值