效果
代码
页面
调用Page
<block wx:for="{{4}}" wx:key="{{item}}"><view style="text-align:center;padding:20px"><swipe-box><view slot="left" style="">左侧内容</view><view class="center" style="height:100px;width:200px;background:#f4f4f4">中间内容</view><view slot="right" style="">右侧内容</view></swipe-box></view>
</block>
SwipeBox wxml
<view class="swipe-box"bindtouchstart="touchstartHandle"bindtouchmove="touchmoveHandle"><view class="content {{direction}}"style="--left--:{{-leftCellWidth}}px;--right--:{{rightCellWidth}}px"><view class="left-handle"><slot name="left"/></view><slot/><view class="right-handle"><slot name="right"/></view></view>
</view>
SwipeBox wxss
.swipe-box {overflow: hidden;display: inline-block;
}.swipe-box > .content {position: relative;display: inline-block;transition: transform .3s;
}.left-handle {position: absolute;right: 100%;top: 0;height: 100%;width: 150px;background: #f3f4fd;
}.content {display: inline-block;
}.right-handle {position: absolute;left: 100%;top: 0;height: 100%;width: 150px;background: #ddd;
}.swipe-box > .content.left {transform: translateX(var(--left--))
}.swipe-box > .content.right {transform: translateX(var(--right--))
}
SwipeBox js
const DISTANCE = 50
Component({options: {addGlobalClass: true,virtualHost: true,multipleSlots: true},externalClasses: ['custom-class'],data: {direction: '',leftCellWidth: 0,rightCellWidth: 0,},lifetimes: {ready() {const vm = thisvm.uuid = wx.guid()//获取左右插槽元素宽度vm.createSelectorQuery().selectAll('.left-handle,.right-handle').boundingClientRect(rects => {vm.setData({leftCellWidth: rects[0].width,rightCellWidth: rects[1].width})}).exec()wx.RE.on('swipe-move', (uuid) => {if (vm.uuid != uuid) {vm.setData({ direction: '' })}})vm.startX = 0vm.startY = 0vm.handleLock = true}},methods: {touchstartHandle(e) {//每次开始先解锁this.handleLock = falsethis.startX = e.changedTouches[0].clientXthis.startY = e.changedTouches[0].clientY},touchmoveHandle(e) {if (this.handleLock) {return}const vm = thislet { startX, startY } = vm;let slidingRange = 45; //let touchMoveX = e.changedTouches[0].clientX;let touchMoveY = e.changedTouches[0].clientY;//当任意方向移动距离大于阈值后判定滑动完成if (Math.abs(touchMoveX - startX) >= DISTANCE || Math.abs(touchMoveY - startY) >= DISTANCE) {vm.handleLock = truelet angle = vm.angle({ X: startX, Y: startY }, { X: touchMoveX, Y: touchMoveY });let direction = '', oldDirection = vm.data.direction//为了方便计算取绝对值判断if (Math.abs(angle) > slidingRange && touchMoveY < startY) {// 向上滑动direction = oldDirection === 'down' ? '' : 'up'}if (Math.abs(angle) > slidingRange && touchMoveY > startY) {// 向下滑动direction = oldDirection === 'up' ? '' : 'down'}if (Math.abs(angle) < 45 && touchMoveX < startX) {// 向左滑动direction = oldDirection === 'right' ? '' : 'left'}if (Math.abs(angle) < 45 && touchMoveX > startX) {// 向右滑动direction = oldDirection === 'left' ? '' : 'right'}vm.setData({ direction })wx.RE.emit('swipe-move', vm.uuid)}},//计算滑动角度 start 起点坐标 end 终点坐标angle(start, end) {//返回角度 Math.atan()返回数字的反正切值return 360 * Math.atan((end.Y - start.Y) / (end.X - start.X)) / (2 * Math.PI);}}
})
备注
代码中出现的如下内容可自行实现
wx.RE
为全局事件管理,用于管理SwipeBox 之间以及与其他内容的交互
guid()
自定义唯一索引函数
参考
滑动方向判断