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: 如發現文中可優化或不當之處,請不吝賜教(。・`ω´・)。