uniapp结合movable-area与movable-view实现拖拽功能2

发布于:2025-02-10 ⋅ 阅读:(39) ⋅ 点赞:(0)

前言

上篇我们写了,固定高度的拖拽,这篇我们将进行不固定高度的拖拽模块编写完成。

开始

一、初始化

我们在list数组里面增加一个data的动态数组,这样可以动态改变元素的高度。

当前元素y = 上一个元素的高度

<template>
  <view style="height: 100%;">
    <movable-area :style="{'width': '100%', 'height': allHeight + 'px'}">
      <movable-view
        v-for="(item, index) in list"
        :key="item.id"
        :x="0"
        :y="item.y"
		:style="{'height': item.itemHeight + 'px', 'width': '100%',}"
        direction="all"
        @touchstart="handleDragStart(index)"
	   @change="handleMoving(index, $event)"
	   @touchend="handleDragEnd"
        class="movable-view"
      >
	  
        <!-- 这里可以放置步骤的详细内容 -->
        <view style="background-color: aqua; padding: 20rpx 0; margin: 10rpx 0;">
			<view v-for="(d_item, d_key) in item['data']" :key="d_key">{{ d_item.name }}</view>
		</view>
		
      </movable-view>
    </movable-area>
  </view>
</template>
 
<script>
export default {
  data() {
    return {
		list: [],
		allHeight: 0,
    };
  },
  
  created() {
	  // 初始化 === 当前y=上一个元素高度(索引为0的y=0)
	  this.list = [
		  {
			  id: 0,
			  itemHeight: 100,
			  y: 0,
			  key: Math.random() + 0,
			  data: [
				  {
					name: '测试0-1'
				  },
				  {
					name: '测试0-2'
				  }
			  ]
		  },
		  {
			  id: 1,
			  itemHeight: 50,
			  y: 100,
			  key: Math.random() + 1,
			  data: [
				  {
					name: '测试1-1'
				  }
			  ]
		  },
		  {
			  id: 2,
			  itemHeight: 50,
			  y: 150,
			  key: Math.random() + 2,
			  data: [
				  {
					name: '测试2-1'
				  }
			  ]
		  },
		  {
			  id: 3,
			  itemHeight: 200,
			  y: 200,
			  key: Math.random() + 3,
			  data: [
				  {
					name: '测试3-1'
				  },
				  {
					name: '测试3-2'
				  },
				  {
					name: '测试3-3'
				  },
				  {
					name: '测试3-4'
				  }
			  ]
		  },
	  ]
	  
  },
  
  methods: {
  },
};
</script>
 
<style>
.movable-area {
 
}
 
.movable-view {
 
}
</style>

二、拖拽实现

y是高度累加,通过ref获取元素高度

<template>
	<view style="height: 100%;">
		<movable-area :style="{'width': '100%', 'height': allHeight + 'px'}">
			<movable-view v-for="(item, index) in list" :key="item.id" :x="0" :y="item.y"
				:style="{'height': item.itemHeight + 'px', 'width': '100%', 'background-color': '#fff'}" direction="all"
				@touchstart="handleDragStart(index)" @change="handleMoving(index, $event)" @touchend="handleDragEnd"
				class="movable-view">

				<!-- 这里可以放置步骤的详细内容 -->
				<view ref="itemRef" style="background-color: aqua; height: 100%; margin: 10rpx 0;">
					<view v-for="(d_item, d_key) in item['data']" :key="d_key">{{ d_item.name }}</view>
				</view>

			</movable-view>
		</movable-area>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				list: [],
				cloneList: [],

				activeIndex: -1, // 选中
				oldIndex: -1,

				moveToIndex: -1, // 移动

				allHeight: 1200,
			};
		},
		mounted() {
			// console.log("===itemRef===", this.$refs.itemRef);
			// if (this.$refs.itemRef) {
			// 	this.$refs.itemRef.forEach((item) => {
			// 		console.log(item.$el.clientHeight)
			// 	});
			// }
		},
		created() {
			// 1.通过ref获取元素高度,并进行计算y轴
			// 2.拖拽时,更换位置(重新计算-高度累积计算)

			// 注意点(总高度不够时,会乱排序)

			// 初始化
			this.list = [{
					id: 0,
					y: 0,
					itemHeight: 100,
					data: [{
							name: '测试0-1'
						},
						{
							name: '测试0-2'
						}
					]
				},
				{
					id: 1,
					y: 100,
					itemHeight: 50,
					data: [{
						name: '测试1-1'
					}]
				},
				{
					id: 2,
					y: 150,
					itemHeight: 50,
					data: [{
						name: '测试2-1'
					}]
				},
				{
					id: 3,
					y: 200,
					itemHeight: 200,
					data: [{
							name: '测试3-1'
						},
						{
							name: '测试3-2'
						},
						{
							name: '测试3-3'
						},
						{
							name: '测试3-4'
						}
					]
				},
			];

			this.cloneList = this.deepCopy(this.list);
		},

		methods: {
			deepCopy(source) {
				return JSON.parse(JSON.stringify(source));
			},

			// 拖拽开始
			handleDragStart(index) {
				this.activeIndex = index;
				this.oldIndex = index;
			},
			handleMoving(index, e) {
				if (e.detail.source !== 'touch') return;
				const {x, y} = e.detail;
				
				let itemHeight = this.list[index]['itemHeight'];
				const currentY = Math.floor((y + itemHeight / 2) / itemHeight);
	
				this.moveToIndex = Math.min(currentY, this.list.length - 1);
				// console.log("===this.moveToIndex===", this.moveToIndex);
			},
			handleDragEnd(e) {
				console.log("=====拖拽结束============");
				if (this.moveToIndex !== -1 && this.activeIndex !== -1 && this.moveToIndex !== this.activeIndex) {
					
					// console.log("===选中目标activeIndex===", this.list[this.activeIndex]);
					// console.log("===移动目标moveToIndex===", this.list[this.moveToIndex]);
					
					// 交互位置
					this.cloneList.splice(this.moveToIndex, 0, ...this.cloneList.splice(this.activeIndex, 1));
					// 计算y轴
					this.cloneList.forEach((item) => {
						item.y = currentY;
      					currentY += item.itemHeight;
					});
					this.list = this.cloneList
				}
				this.activeIndex = -1;
				this.oldIndex = -1;
				this.moveToIndex = -1;
			},
		},
	};
</script>

<style>
	.movable-area {}

	.movable-view {}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到