现在大部分的人都喜欢使用手势图案锁来作为手机的锁屏,之前我也写过一篇使用vue封装的手势图案锁组件,想了解的可以戳这里->《vue封装一个图案手势锁组件》。那么怎么在微信小程序中实现这种手势锁屏的效果的呢?接下来让我们一起来实现一个微信小程序中可以使用的手势锁屏组件吧!
我们主要从页面展示效果和交互效果来进行具体分析:
使用flex布局和flex-wrap效果,使9个圆点可以均匀排列。
<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>
.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;
}
只需要动态判断当前圈圈是否被选中,动态修改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>
我们可以对整个组件界面进行一个触屏监听,判断坐标是否经过某一个圆点的坐标,如果是,可以将当前圆点标记为选中状态。
<view
id="j-apps-lock-body"
class="j-apps-lock-body"
bindtouchstart="mousedown"
bindtouchmove="mouseover"
bindtouchend="mouseup"
>
...
view>
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
})
},
在手指离开手机屏幕,及触屏事件结束触发mouseup事件的时候,将选中的圈圈坐标顺序传递给父组件,这里我对圈圈的坐标定义如下,大家也可以根据实际情况自己定义:
mouseup(){
this.triggerEvent("getPassword", {chooseList:this.data.chooseList});
},
所以上图的图案滑动轨迹返回的点集数组应该为:
[1,2,3,6,9,8,7,4,5]
在进行点坐标判断的时候,我们需要获取到每一个点的坐标范围,但是在微信小程序中我们不能直接同document.getElementbyId去获取到我们需要的实例对象,那么我们该怎么获取到需要的对象,并得到其相应的坐标范围呢?
我们需要先了解一下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()
},
前面我们获取的点位的dom实例在这里就可以派上用场了,微信小程序返回的实例对象中会包含这几个属性:
我们可以直接根据实例对象的四个端点坐标来进行一个正方形的大致位置匹配,这样得出来的结果会有少许误差,但也不会有很大的影响: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
})
},
我们也可以根据点实例对象的端点得出其圆的方程,我们只需要将坐标代入方程判断是否位于圆内即可:
(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前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球 ,也喜欢写些东西,既为自己记录,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解,写错的地方望指出,定会认真改进,在此谢谢大家的支持,我们下文再见。