movable-view
组件。movable-view。position: absolute;
,将可滑动部分(z-index
值较大)放置在删除按钮(z-index
值较小)之上,最开始是遮住删除按钮的。touchstart
、touchend
属性绑定方法,控制删除按钮的显示隐藏。<view class="container">
<movable-area>
<movable-view direction="horizontal" out-of-bounds="{{true}}" friction="150" x="{{x}}" bindtouchstart="handleTouchStart" bindtouchend="handleTouchEnd" >
<view class="card-container">
<view>{{text}}</view>
<view class="show-operations" catchtouchstart="toggle" catchtouchend="emptyFunc">...</view>
</view>
</movable-view>
</movable-area>
<view class="operations-content" >
<view class="operation-button" catchtap="handleDelete">
删除
</view>
</view>
</view>
复制代码
在使用movable-view
中用到的属性:javascript
direction="horizontal"
,设置movable-view
为横向移动。out-of-bounds="{{true}}"
,设置超过区域以后,movable-view
是否还能够移动,这个属性默认值为false
,若是不添加这个属性,就不会有回弹效果。friction="150"
设置摩擦系数,摩擦系数越大,滑动越快中止。x="{{x}}"
设置x轴方向的偏移。tip: movable-view 必须设置width和height属性,不设置默认为10px。
tip: movable-view 默认为绝对定位,top和left属性为0pxcss
更多内容参考:movable-view。html
由于movable-view
默认为绝对定位,因此设置删除按钮部分的z-index
值比movable-view
的z-index
小,就能将删除按钮遮住。java
/* 可移动部分样式 */
movable-area {
width: 510rpx;
}
.container,
movable-view {
box-sizing: border-box;
width: 750rpx;
height: 200rpx;
}
.container {
position: relative;
display: flex;
flex-direction: row;
}
movable-view {
z-index: 5;
padding: 10rpx;
overflow: hidden;
background-color: green;
}
/* 隐藏部分样式 */
.operations-content {
position: absolute;
display: flex;
flex-direction: row-reverse;
justify-content: left;
align-items: center;
z-index: 2;
right: 0;
width: 280rpx; /* 隐藏部分的宽度 */
height: 200rpx;
background-color: yellow;
}
.operation-button {
width: 150rpx;
height: 150rpx;
line-height: 150rpx;
text-align: center;
border-radius: 50%;
margin: 0 20rpx;
background-color: gray;
color: #fff;
}
/* 卡片样式 */
.card-container {
width: 100%;
height: 180rpx;
border-radius: 5rpx;
font-size: 20px;
word-break: break-all;
background-color: rgba(255, 255, 255, 0.7);
}
.show-operations {
position: absolute;
bottom: 10rpx;
right: 10rpx;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
text-align: center;
line-height: 80rpx;
}
复制代码
经过控制movable-view
的x
属性来控制删除按钮的显示和隐藏。json
绑定movable-view
的touchstart
和touchend
事件,记录下触摸开始时的x轴坐标start_x
和触摸结束时的x轴坐标current_x
,若是current_x - start_x
小于0就说明是朝左滑的,设置movable-view
的x
为-140
来显示删除按钮,不然就是向右滑的,经过设置x
值为0
来隐藏删除按钮。小程序
Component({
properties: {
text: {
type: String,
value: '示例内容示例内容'
},
index: Number
},
data: {
x: 0, // 注意,这里经过x属性设置的宽度的单位是px
start_x: 0,
operations_visible: false
},
methods: {
handleTouchStart: function (event) {
this.setData({
start_x: event.touches[0].clientX // 触摸开始时的横坐标
})
},
handleTouchEnd: function (event) {
const current_x = event.changedTouches[0].clientX; // 触摸结束时的横坐标
const { start_x } = this.data;
const direction = current_x - start_x; // 判断滑动的方向
if (direction < 0) {
this.showOperations();
} else {
this.hideOperations();
}
},
toggle: function () {
let operations_visible = this.data.operations_visible;
if (operations_visible) {
this.hideOperations();
} else {
this.showOperations();
}
},
handleDelete () {
const index = this.properties.index;
this.hideOperations();
this.triggerEvent('delete', { index });
},
showOperations: function () {
this.setData({
x: -140,
operations_visible: true
});
},
hideOperations: function () {
this.setData({
x: 0,
operations_visible: false
});
},
emptyFunc: function () {
return false;
}
}
})
复制代码
在显示隐藏的部分能够作一个优化,在显示状态下左滑和在隐藏状态下右滑,不用设置x
的值。微信小程序
handleTouchEnd: function (event) {
const operations_visible = this.data.operations_visible;
const current_x = event.changedTouches[0].clientX; // 触摸结束时的横坐标
const { start_x } = this.data;
const direction = current_x - start_x; // 判断滑动的方向
if (direction < 0) {
!operations_visible && this.showOperations();
} else {
operations_visible && this.hideOperations();
}
},
复制代码
{
"component": true
}
复制代码
movable-area
的宽度可以解决这个问题。
movable-area {
width: 510rpx;
}
复制代码
这里将movable-area
的宽度设置为510rpx
,而不是(750-280=470
)470rpx
,就能让回弹的范围在黄色部分,“隐藏”这个空隙。数组
必须设置movable-area
的宽度,不然默认宽高为10px
,movable-view
可滑动的范围会更大,在滑动的过程当中会出现中间空隙很大的状况。bash
movable-view
中添加了bindtouchstart
和bindtouchend
属性用于绑定触摸开始事件和触摸结束事件。在子元素中有三个点,点击三个点的时候可以切换删除按钮的显示和隐藏。可是使用bindtap
属性绑定元素的点击事件,父元素上绑定的触摸事件也会被触发。因此须要使用catch
绑定事件来阻止事件冒泡。<view class="show-operations" catchtouchstart="toggle" catchtouchend="emptyFunc">...</view>
复制代码
emptyFunc: function () {
return false;
}
复制代码
(1)滑动速度比较慢。微信
解决方法:调整属性,使滑动的效果变快。
<movable-view direction="horizontal" out-of-bounds="{{true}}" damping="100" friction="100" x="{{x}}"
bind:touchstart="handleTouchStart" bind:touchend="handleTouchEnd">
复制代码
(2)当上下滑动的过程当中,会误触发左右滑动。
解决方法:获取滑动起始和结束时的clientY
,当二者差值的绝对值大于某个范围的时候,就认为是纯上下滑动,不触发左右滑动。
(3)当点击卡片时,会误触发左右滑动。
解决方法:使用1而不是0来判断左右滑
handleTouchStart: function (event) {
this.hideAllOperations();
const { clientX, clientY } = event.touches[0];
this.setData({
start_x: clientX,
start_y: clientY
});
},
handleTouchEnd: function (event) {
const { clientX, clientY } = event.changedTouches[0];
const { start_x, start_y } = this.data;
if (Math.abs(clientY - start_y) > 50) return; // 处理上下滑动误触左右滑动的状况
const direction = clientX - start_x;
// 这里使用1来判断方向,保证用户在非滑动时不触发滚动(有时点击也会产生些许x轴坐标的变化)
if (direction < -1) {
this.showOperations();
} else if (direction > 1) {
this.hideOperations();
} else {
this.toBrandDetail();
}
},
复制代码
(4)在列表中只能有一个隐藏的按钮是显示出来的,可是当前的方式没有对滑动卡片的数量作限制。
解决方法:在父组件中定义一个数组(数组元素为滑动卡片的x
值),用于控制全部卡片的显示隐藏。当滑动开始时将数组中的全部值设置为0
,当左滑显示卡片的时候,将滑动显示出按钮的那个卡片对应的数组中的x值设置为-85
。
更多微信小程序事件相关,参考:微信小程序事件。
若是要以列表的形式使用,就在父组件中引入该组件,并经过数组来控制列表。
父组件的wxml:
<view>
<block wx:for="{{test_list}}" wx:key="{{index}}">
<movable-component text="{{item}}" index="{{index}}" class="list-item" catch:delete="deleteItem"/>
</block>
</view>
复制代码
父组件的js:
Page({
data: {
test_list: null
},
onLoad: function () {
let list_arr = [];
for (let i = 0; i < 5; i++) {
list_arr.push(`${Array(10).fill(i + 1).join(' ')}`);
}
this.setData({
test_list: list_arr
})
},
deleteItem: function (event) {
// 一些其他操做,好比发起删除请求
const index = event.detail.index;
let arr = this.data.test_list;
arr.splice(index, 1);
this.setData({
test_list: arr
})
}
})
复制代码
父组件的wxss:
.list-item {
display: block;
margin: 20rpx 0;
}
复制代码
父组件的json:
{
"usingComponents": {
"movable-component": "./components/movableView/movableView"
}
}
复制代码
PS: 如发现文中可优化或不当之处,请不吝赐教(。・`ω´・)。