微信小程序滑动删除(真机测试下可用),通过css3 transform实现
刚接触微信小程序不久,在做的项目是个微商城. 其中购物车中需要用到滑动删除功能. 原本在其他平台上利用JS操作DOM计算坐标即可完成,但是小程序的bindtouchmouve,bindtouchend和bindtouchstart事件会冒泡到父级控件,在真机测试中会导致整屏都触发自定义的滑动事件,真个界面都成了万花筒. 如果使用catchtouchmove,catouchend和catchstart. 是可以防止冒泡. 左右也可以正常滑动.但是不仅仅是小程序的横向scroll事件,小程序的纵向scroll事件也会无法触发. 也就是会导致当前页面无法上下滑动.
我试过用scroll-view控件, 在小程序官方文档中说明scroll-x="false"能禁止x轴滚动. 实际上不管在真机还是微信开发者中都无法起作用. 后来经过多方实验,发现只要滑动模块超过当前屏幕可视宽度,bindtouchmove就会冒泡进而触发整屏滑动,即使删除按钮只是用绝对定位固定在右侧也不行, 例如下图windowWidth为414px, 产品Item宽也是414px,但是加上删除按钮就超出了414px. 滑动时就会触发整屏滑动.
实在没有办法,后来想到Css3里面的transform变换也可以实现移动的效果,而且移动的距离是不是不计入模块的宽度呢?首先先用删除按钮做测试:
把删除按钮用绝对定位定在Item内右侧,然后利用transform平移到item外右侧. 用真机测试,果然左右滑动不会再触发整个View的滑动了.
1 .item .btn-del{
2 position: absolute;
3 display: flex;
4 top:0px;
5 right:0px;
6 color: #fff;
7 background: #fd4346;
8 height: 100%;
9 border-radius: 0px;
10 border: none;
11 align-items: center;
12 transform:translate(64px,0);
13 -ms-transform:translate(64px,0);
14 -moz-transform:translate(64px,0);
15 -webkit-transform:translate(64px,0);
16 -o-transform:translate(64px,0);
17 }
接下来很简单只要把item也利用transform跟随用户手势左右平移即可. 计算用户平移距离和平常一样,我写的比较粗糙,随便一看,
WXML:
<view class="item" data-matindex="{{matIndex}}"
bindtouchend="touchEndToDel" bindtouchstart="touchStartToDel" bindtouchmove="touchMoveToDel"
style="webkit-transform:translate({{matItem.moveLeft}}px,0);-webkit-transform:translate({{matItem.moveLeft}}px,0);"
wx:for="{{matList}}" wx:for-item="matItem" wx:for-index="matIndex" wx:key="skuguid">
<view class="shop-image" >
<icon wx:if="{{matItem.selected}}" type="success" size="20" color="#2da4e6" class="my-check"/>
<icon wx:else type="circle" size="20" class="my-check"/>
<image src="{{matItem.imageaddress}}" style="width:180rpx;height:180rpx;"></image>
</view>
<view class="shop-title" bindtap="tapBackDelBtn"data-matindex="{{matIndex}}">
<text>{{matItem.matname}}</text>
<view class="h2 num" wx:if="{{mat.isEdit}}">
<view class="flex flex-wrap" >
<view bindtap="minusNum" data-matindex="{{matIndex}}" class="flex-item">-</view>
<view class="flex-item">
<input type="text" value="{{matItem.digit}}"/>
</view>
<view bindtap="plusNum" data-matindex="{{matIndex}}" class="flex-item">+</view>
</view>
</view>
<view class="price">{{matItem.showprice}}</view>
</view>
<view class="shop-price" >
<view></view>
<view>x{{matItem.digit}}</view>
</view>
<!-- 弹出按钮-删除 -->
<button bindtap="removeSingle" wx:if="{{!mat.isEdit }}" data-matindex="{{matIndex}}" class="btn-del" >删除</button>
</view>
</view>
var moveXList = [0, 0]//X轴移动的距离
/**
* 轻触回收指定删除按钮
*/
tapBackDelBtn:function(e){var matIndex = e.currentTarget.dataset.matindex
that.backDelBtn(matIndex)
},
/**
* 收回弹出删除按钮
* matIndex:skuBody下标
* 如果不传表示全部收回
*/
backDelBtn:function(matIndex){
if (!vpUtilService.vpIsNull(matIndex)){
that.data.matList.forEach(function(item,index){
item.moveLeft = 0
})
} else {
that.data.matList[matIndex].moveLeft = 0
}
that.setData({ matList: that.data.matList})
},
/**
* bindtouchmove
*/
touchMoveToDel:function(e){
if (e.touches.length != 1 ){return}
if (moveXList[1] == 0){
moveXList.shift()
moveXList.push(e.touches[0].clientX)
return
}var matIndex = e.currentTarget.dataset.matindex
var moveLeft = that.data.matList[matIndex].moveLeft
if ((moveLeft<=0) || (moveLeft>-64)){//移动范围在 -64px~0之间
var dis = moveXList[1] - moveXList[0]
moveLeft = parseInt(moveLeft?moveLeft:0) + parseInt(dis)
moveLeft = moveLeft < -64? -64: moveLeft
moveLeft = moveLeft > 0 ? 0 : moveLeft
moveXList.shift()
moveXList.push(e.touches[0].clientX)
that.data.matList[matIndex].moveLeft = moveLeft
that.setData({ matList: that.data.matList})
}
},
/**
* bindtouchend
*/
touchEndToDel: function (e) {
var matIndex = e.currentTarget.dataset.matindex
var moveLeft = that.data.matList[matIndex].moveLeft
if(moveLeft<-32){//移动超过一半的距离,弹出删除按钮
that.data.matList[matIndex].moveLeft = -64
}else{//小于一半的距离,收回
that.data.matList[matIndex].moveLeft = 0
}
that.setData({ matList: that.data.matList})
},
/**
* bindtouchstart
*/
touchStartToDel: function (e) {
moveXList = [0,0]
},