发布时间:2022-07-26
微信小程序拖拽排序
问题:拖拽区域,在非拖拽时候 ,进行 手势上下滑动
思路一:每个所需要排序的view,增加 排序 ico 按钮,点击后,拖拽取件生效,反之,禁止
.wxss文件
movable-view {
pointer-events: auto;
}
movable-area {
pointer-events: none;
}
父级 pointer-events: none; 父级设置 禁用鼠标手势事件,,即可实现上下滑动
子级(需要鼠标,手势事件的区域) 设置为 pointer-events: auto;
思路二: 判断手势 上下滑动,如果上下滑动,拖拽取件 禁止,默认生效
。。官方没找到 上下左右滑动
<movable-area class="movable-container wx:if='{{movale_ok == 1 ? 'area_events' : 'area_events_auto'}}'" style="height: {{ elementHeight * list.length + 40 * list.length }}px;" catch:touchmove="onHackTouchMove">
<block wx:for="{{ list }}" wx:key="index">
<view class="index_view {{ dragElement && dragElement.id === item.id ? 'item--tran' : '' }} {{ lastTarget === index ? 'item--target' : '' }}" data-index="{{ index }}" bind:longpress="onLongPress" bind:touchmove="onTouchMove" bind:touchend="onTouchEnd">
<view class="index_view_p">
<text>{{ item.bj_title }}</text>
<text>当前进度:{{ item.jidnu }}</text>
<text>{{ item.zhouqi }}</text>
<text bindtap="on_student">{{ item.renshu }}名学员--查看</text>
</view>
<view class="column_view_index">
<van-icon name="bars" size='45rpx' style="align-self:flex-end;" data-index="{{ index }}" bind:longpress="onLongPress" bind:touchmove="onTouchMove" bind:touchend="onTouchEnd" color='#999999' style="pointer-events: auto;" />
<van-button icon="arrow" color='#73BEC9' type="primary" bindtap="on_course" />
</view>
</view>
</block>
<!-- HACK: animation设置为false,避免开始显示此组件的滑动效果 -->
<movable-view hidden="{{ !dragElement }}" class="index_view_mo " style='height: {{ elementHeight }}px;' direction="vertical" disabled animation="{{ false }}" y="{{ movableViewY }}">
<view class="index_view_p_mo">
<text>{{ dragElement.bj_title }}</text>
<text>当前进度:{{ dragElement.jidnu }}</text>
<text>{{ dragElement.zhouqi }}</text>
<text>{{ dragElement.renshu }}名学员</text>
</view>
<!-- <van-button icon="arrow" color='#73BEC9' type="primary" /> -->
</movable-view>
</movable-area>
/* pages/index/index.wxss */
.van-field__control {
background-color: #fff;
}
.column_view_index {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 200rpx;
}
.index_head {
display: flex;
justify-content: space-between;
align-items: center;
margin: 20rpx 0;
}
.index_view {
background-color: #9999990f;
margin: 20rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
}
.index_view_p {
display: flex;
flex-direction: column;
line-height: 60rpx;
}
.index_view_mo {
background-color: #73BEC9a6;
display: flex;
justify-content: space-between;
align-items: center;
width: 90%;
padding: 30rpx;
}
.index_view_p_mo {
display: flex;
flex-direction: column;
line-height: 60rpx;
color: #fff;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
.movable-container {
width: 100%;
}
.item--tran {
background-color: #9999990f;
}
.item--target {
background-color: #73BEC9;
}
.view_events {
pointer-events: auto;
}
.view_events_none {
pointer-events: none;
}
.area_events {
pointer-events: none;
}
.area_events_auto {
pointer-events: auto;
}
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
// 排序状态码
movale_ok: 1,
value: '',
//#region 纯数据字段
/** 屏幕高度,单位px */
_windowHeight: null,
/** 开始触摸时的单一项左上角y坐标 */
_startOffsetY: null,
/** 开始触摸位置y坐标 */
_startPageY: null,
/** 开始触摸项索引 */
_startDragElementIndex: null,
/** 滑动偏移 */
_scrollThreshold: 0.5,
/** 距顶部/左边多远时,触发 _scrollToUpper 事件,单位px,即上滑至屏幕顶部 */
_upperThreshold: 100,
/** 距底部/右边多远时,触发 _scrollToLower 事件,单位px,即下滑至屏幕底部 */
_lowerThreshold: 100,
/** 上滑和下滑时间,单位毫秒 */
_scrollDuration: 1000,
//#endregion
/** 列表 */
list: [{
id: 1,
content: 1,
bj_title: '21级秋季 - 本科定制班 - 1班',
jidnu: '第10章 第10节',
zhouqi: '2022.06-2023.10',
renshu: '60'
}, {
id: 2,
content: 2,
bj_title: '21级秋季 - 本科定制班 - 2班',
jidnu: '第10章 第10节',
zhouqi: '2022.06-2023.10',
renshu: '60'
}, {
id: 3,
content: 3,
bj_title: '21级秋季 - 本科定制班 - 3班',
jidnu: '第10章 第10节',
zhouqi: '2022.06-2023.10',
renshu: '60'
}, {
id: 3,
content: 3,
bj_title: '21级秋季 - 本科定制班 - 3班',
jidnu: '第10章 第10节',
zhouqi: '2022.06-2023.10',
renshu: '60'
}, {
id: 3,
content: 3,
bj_title: '21级秋季 - 本科定制班 - 3班',
jidnu: '第10章 第10节',
zhouqi: '2022.06-2023.10',
renshu: '60'
}, {
id: 4,
content: 4,
bj_title: '21级秋季 - 本科定制班 - 4班',
jidnu: '第10章 第10节',
zhouqi: '2022.06-2023.10',
renshu: '60'
}],
/** 单一项高度 */
elementHeight: 120,
/** 滑动项 */
dragElement: null,
/** movable-view组件y轴坐标,滑动时滑动项左上角距离文档顶部纵坐标,单位px */
movableViewY: null,
/** 滑动过程中经过的项 */
lastTarget: null,
},
onLoad: function (options) {},
on_course: function () {
wx.navigateTo({
url: '/pages/course/course',
})
},
on_student: function () {
wx.navigateTo({
url: '/pages/student/student',
})
},
/** 生命周期函数--监听页面展示 */
onShow() {
this._getWindowHeight();
},
/** 长按触发事件 */
onLongPress(event) {
let dragElementIndex = event.currentTarget.dataset.index;
let dragElement = this.data.list[dragElementIndex];
let movale_ok = this.data.movale_ok
this.setData({
/** 点击项左上角y坐标 */
_startOffsetY: event.target.offsetTop,
/** 点击位置y坐标 */
_startPageY: event.touches[0].pageY,
/** 点击项索引 */
_startDragElementIndex: dragElementIndex,
/** 点击项 */
dragElement,
/** movable-view组件左上角y坐标 */
movableViewY: event.target.offsetTop,
movale_ok: 0
});
console.log(movale_ok);
},
onPaixu() {
let movale_ok = this.data.movale_ok
this.setData({
movale_ok: 0
});
},
/**
* 手指触摸后移动
* - 触底或触顶时下滑或者上滑
* - 移动movable-view
*/
onTouchMove(event) {
// console.log('[onTouchMove]', event);
// 长按事件
if (this.data.dragElement) {
let clientY = event.touches[0].clientY; // 触摸点位置在显示屏幕区域左上角Y坐标
this._pageScroll(clientY);
/** 触摸点位置距离文档左上角Y坐标 */
let pageY = event.touches[0].pageY;
/** 和最初点击位置比较移动距离 */
let targetMoveDistance = pageY - this.data._startPageY;
/** 移动后的movable-view组件位置 */
let movableViewY = this.data._startOffsetY + targetMoveDistance;
/** 经过项索引 */
let targetIndex = this._computeFutureIndex(targetMoveDistance, this.data._startDragElementIndex);
this.setData({
movableViewY,
lastTarget: targetIndex
});
}
},
/** 滑动结束 */
onTouchEnd(event) {
// console.log('[onTouchEnd]', event);
if (this.data.dragElement) {
let list = this._deepCopy(this.data.list);
/** 结束点位置y坐标 */
let pageY = event.changedTouches[0].pageY;
/** 和初始点击位置比较移动距离 */
let targetMoveDistance = pageY - this.data._startPageY;
/** 初始点击项索引 */
let dragElementIndex = this.data._startDragElementIndex;
/** 目标项索引 */
const futureIndex = this._computeFutureIndex(targetMoveDistance, dragElementIndex);
if (futureIndex !== false) {
list.splice(futureIndex, 0, list.splice(dragElementIndex, 1)[0]); // 移动位置
}
var movale_ok = this.data.movale_ok
this.setData({
list,
dragElement: null,
lastTarget: null,
movale_ok: 1
});
console.log(movale_ok);
}
},
/** 阻止滑动 */
onHackTouchMove() {},
/** 获取可使用窗口高度,单位px */
_getWindowHeight() {
try {
const {
windowHeight
} = wx.getSystemInfoSync();
this.setData({
_windowHeight: windowHeight
});
} catch (err) {
console.error('[_getWindowHeight]', err);
}
},
/** 页面滑动 */
_pageScroll(clientY) {
if (clientY + this.data._upperThreshold >= this.data._windowHeight) {
// 下滑接近屏幕底部
wx.pageScrollTo({
scrollTop: clientY + this.data.elementHeight,
duration: this.data._scrollDuration
});
} else if (clientY - this.data._lowerThreshold <= 0) {
// 上滑接近屏幕顶部
wx.pageScrollTo({
scrollTop: clientY - this.data.elementHeight,
duration: this.data._scrollDuration
})
}
},
/**
* 计算目标索引
* @param {number} targetMoveDistance 移动距离
* @param {number} dtagElementIndex 初始移动项索引
* 若轻轻拂动则返回false
*/
_computeFutureIndex(targetMoveDistance, dragElementIndex) {
let willInsertAfter = this._getSwapDirection(targetMoveDistance);
if (willInsertAfter !== false) {
/** 偏移索引 */
let offsetElementIndex = dragElementIndex + willInsertAfter;
/** 移动步数 */
let step = targetMoveDistance / this.data.elementHeight;
/** 步数补偿,当只有移动距离超过单项 _scrollThreshold 时才算有效 */
if (step <= -1) {
step += this.data._scrollThreshold;
} else if (step >= 1) {
step -= this.data._scrollThreshold;
}
/** 目标索引 */
let futureIndex = parseInt(step) + offsetElementIndex;
// 避免越界
if (futureIndex < 0) {
futureIndex = 0;
} else if (futureIndex > this.data.list.length - 1) {
futureIndex = this.data.list.length - 1;
}
return futureIndex;
} else {
return willInsertAfter;
}
},
/**
* 获取滑动方向
* @param {number} targetMoveDistance 移动距离
* @returns {number/boolean}
* - 1 下滑
* - -1 上滑
* - false 拂动,滑动距离小于一半单项高度
*/
_getSwapDirection(targetMoveDistance) {
if (Math.abs(targetMoveDistance) < this.data.elementHeight / 2) {
// 轻轻拂动,滑动距离小于1/2单项高度
return false;
} else if (targetMoveDistance >= this.data.elementHeight / 2) {
return 1; // 下滑
} else if (targetMoveDistance <= this.data.elementHeight / -2) {
return -1; // 上滑
}
},
/** 深拷贝 */
_deepCopy(obj) {
// 只拷贝对象
if (typeof obj !== 'object') return;
// 根据obj的类型判断是新建一个数组还是一个对象
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
// 遍历obj,并且判断是obj的属性才拷贝
if (obj.hasOwnProperty(key)) {
// 判断属性值的类型,如果是对象递归调用深拷贝
newObj[key] = typeof obj[key] === 'object' ? this._deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
})
发表评论
留言: