前言
当你在使用微信小程序时,是否曾经遇到过左滑操作是如此的顺畅,让你想起了 iPhone 上的滑动操作?左滑操作在微信小程序中已经成为了一个常见的交互方式,它能够帮助用户快速地执行某些操作,提高了用户的使用体验。那么,你是否好奇这个左滑操作是如何实现的呢?本文将会为你揭秘微信小程序左滑操作背后的技术原理。
实现效果:
实现思路
- 首先我们需要为容器添加
bindtouchstart
(手指触摸屏幕触发)、bindtouchmove
(手指在屏幕上滑动的时候连续触发); bindtouchstart
事件第一次触发时就是手指点击屏幕的开始,也就是起点x坐标;其中,我们需要清除左滑的所有内容,只操作isTouchMove
值为true
的;bindtouchmove
事件中开始滑动,记录开始滑动的x
、y
坐标、滑动时变化的x
、y
坐标以及滑动的角度,通过Math.abs
函数返回指定数字x
的绝对值;- 计算滑动的角度,
start
为起点坐标,end
为终点坐标,通过Math.atan()
函数返回一个数值的反正切(以弧度为单位); - 为左滑出来的内容添加点击事件操作,在js中触发点击事件
passEvent
(审核通过)、notGoEvent
(审核不通过)执行操作。
源码如下:
wxml文件
<view>
<!-- 判断item.isTouchMove是否为true,为true则添加leftLaterBox类名,否则就不用管。-->
<!-- data-index="{{index}}" 获取节点绑定数据 -->
<view class="leftSideBox {{item.isTouchMove ? 'leftLaterBox' : ''}}" data-index="{{index}}" bindtouchstart="touchstart" bindtouchmove="touchEvent" wx:for="{{listData}}" wx:key="index">
<!-- 展示循环的listData数组的每一条数据 -->
<view class="txtBox">
<text>{{index+1}}</text>
<text>{{item.itemTxt}}</text>
</view>
<!-- 操作按钮 默认不显示 -->
<view style="background-color: #6495ED;" class="auditBox" catchtap="passEvent" data-index="{{index}}">
审核通过</view>
<view class="auditBox" catchtap="notGoEvent" data-index="{{index}}">审核不通过</view>
</view>
</view>
js文件
var app = getApp(); //获取应用实例
Page({
data: {
startX: 0, //开始x坐标
startY: 0, //开始y坐标
listData: [{
itemTxt: "第一条消息",
},
{
itemTxt: "第二条消息",
},
{
itemTxt: "第三条消息",
},
{
itemTxt: "第四条消息",
},
{
itemTxt: "第五条消息",
},
{
itemTxt: "第六条消息",
},
{
itemTxt: "第七条消息",
},
{
itemTxt: "第八条消息",
},
{
itemTxt: "第九条消息",
}
], //模拟数据
},
onLoad: function () {},
//手指触摸动作开始 记录起点X坐标
touchstart: function (e) {
//开始触摸,重置所有左滑内容
this.data.listData.forEach(function (item, idx) {
if (item.isTouchMove) //只操作为true的
item.isTouchMove = false;
})
this.setData({
startX: e.changedTouches[0].clientX,
startY: e.changedTouches[0].clientY,
listData: this.data.listData
})
},
//滑动事件
touchEvent(e) {
var that = this, //防止this指向问题
index = e.currentTarget.dataset.index, //当前下标
startX = that.data.startX, //开始X坐标
startY = that.data.startY, //开始Y坐标
touchMoveX = e.changedTouches[0].clientX, //滑动变化x坐标
touchMoveY = e.changedTouches[0].clientY, //滑动变化y坐标
//获取滑动角度
angle = that.angle({
X: startX,
Y: startY
}, {
X: touchMoveX,
Y: touchMoveY
});
that.data.listData.forEach(function (item, idx) {
item.isTouchMove = false
//滑动超过30度,函数返回指定数字 x 的绝对值
if (Math.abs(angle) > 30) return;
if (idx == index) {
if (touchMoveX > startX) //右滑
item.isTouchMove = false
else //左滑
item.isTouchMove = true
}
})
//更新数据
that.setData({
listData: that.data.listData
})
},
// 计算滑动角度,start 起点坐标,end 终点坐标
angle: function (start, end) {
var _X = end.X - start.X,
_Y = end.Y - start.Y
//返回角度 Math.atan()函数返回一个数值的反正切(以弧度为单位)
return 360 * Math.atan(_Y / _X) / (2 * Math.PI);
},
//审核通过事件
passEvent(e) {
console.log(e, "审核通过下标");
// 请求接口执行操作
wx.showToast({
title: '审核通过',
icon: 'none',
duration: 800
})
this.setData({
listData: this.data.listData
})
},
// 审核不通过事件
notGoEvent(e) {
console.log(e, "审核不通过下标");
// 请求接口执行操作
wx.showToast({
title: '审核不通过',
icon: 'none',
duration: 800
})
this.setData({
listData: this.data.listData
})
},
})
wxss文件
.leftSideBox {
/* 最外层盒子的样式 */
width: 100%;
overflow: hidden;
display: flex;
justify-content: space-between;
font-size: 28rpx;
border-bottom: 2rpx solid gainsboro;
}
.leftLaterBox .txtBox,
.leftLaterBox .auditBox {
/* 设置每一个块左滑 */
-webkit-transform: translateX(0);
transform: translateX(0);
}
.txtBox {
/* 循环的每一个块的样式 */
width: 100%;
padding: 30rpx 12rpx;
-webkit-transition: all 0.4s;
transition: all 0.4s;
-webkit-transform: translateX(360rpx);
transform: translateX(360rpx);
margin-left: -360rpx
}
.txtBox text {
/* 文字样式 */
padding: 0rpx 4rpx;
}
.auditBox {
/* 左滑出来的按钮样式 */
width: 180rpx;
background: rgb(243, 98, 98);
color: white;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
-webkit-transform: translateX(360rpx);
transform: translateX(360rpx);
-webkit-transition: all 0.4s;
transition: all 0.4s;
}