uniapp自定义拖拽排列

uniapp自定义拖拽排列并改变下标

javascript 复制代码
<!-- 页面模板 -->
<template>
	<view class="container">
		<view v-for="(item, index) in list" :key="item.id" class="drag-item" :style="{
        transform: `translate(${activeIndex === index ? offsetX : 0}px, ${activeIndex === index ? offsetY : 0}px)`,
        transition: activeIndex === index ? 'none' : 'transform 0.3s',
        zIndex: activeIndex === index ? 999 : 1,
        boxShadow: activeIndex === index ? '0 8px 20px rgba(0,0,0,0.2)' : '0 2px 6px rgba(0,0,0,0.1)'
      }" @touchstart="handleTouchStart(index, $event)" @touchmove="handleTouchMove(index, $event)"
			@touchend="handleTouchEnd">
			{{ item.content }}
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				list: [
				{ id: 1, content: 'Item 1' },
				{ id: 2, content: 'Item 2' },
				{ id: 3, content: 'Item 3' },
				{ id: 4, content: 'Item 4' },
				{ id: 5, content: 'Item 5' },
				{ id: 6, content: 'Item 6' },
				{ id: 7, content: 'Item 7' },
				{ id: 8, content: 'Item 8' },
				{ id: 9, content: 'Item 9' },
				{ id: 10, content: 'Item 10' },
				{ id: 11, content: 'Item 11' },
				{ id: 12, content: 'Item 12' },
				{ id: 13, content: 'Item 13' },
				{ id: 14, content: 'Item 14' },
				], 
				activeIndex: -1, // 当前激活元素索引
				startX: 0, // 触摸起始X坐标
				startY: 0, // 触摸起始Y坐标
				offsetX: 0, // X轴偏移量
				offsetY: 0, // Y轴偏移量
				positions: [] // 元素位置缓存数组:ml-citation{ref="1,3" data="citationList"}
			}
		},
		mounted() {
			// this.initPositions()
		},
		methods: {
			// 初始化元素位置信息:ml-citation{ref="3,5" data="citationList"}
			initPositions() {
				uni.createSelectorQuery().in(this).selectAll('.drag-item')
					.boundingClientRect(rects => {
						this.positions = rects.map(rect => ({
							left: rect.left,
							top: rect.top,
							width: rect.width,
							height: rect.height
						}))
					}).exec()
			},

			// 触摸开始事件:ml-citation{ref="2,7" data="citationList"}
			handleTouchStart(index, e) {
				this.activeIndex = index
				this.startX = e.touches[0].clientX
				this.startY = e.touches[0].clientY
				this.initPositions()
			},

			// 触摸移动事件:ml-citation{ref="4,8" data="citationList"}
			handleTouchMove(index, e) {
				if (index !== this.activeIndex) return

				const currentX = e.touches[0].clientX
				const currentY = e.touches[0].clientY
				this.offsetX = currentX - this.startX
				this.offsetY = currentY - this.startY

				// 查找目标位置:ml-citation{ref="1,6" data="citationList"}
				const targetIndex = this.findTargetIndex(currentX, currentY)
				if (targetIndex !== -1 && targetIndex !== this.activeIndex) {
					this.swapElements(this.activeIndex, targetIndex)
					this.activeIndex = targetIndex
					this.startX = currentX
					this.startY = currentY
					this.offsetX = 0
					this.offsetY = 0
				}
			},

			// 查找目标插入位置:ml-citation{ref="5,6" data="citationList"}
			findTargetIndex(x, y) {
				for (let i = 0; i < this.positions.length; i++) {
					const pos = this.positions[i]
					if (x > pos.left && x < pos.left + pos.width &&
						y > pos.top && y < pos.top + pos.height) {
						return i
					}
				}
				return -1
			},

			// 交换数组元素:ml-citation{ref="2,7" data="citationList"}
			swapElements(oldIndex, newIndex) {
				const temp = [...this.list]
				const movedItem = temp.splice(oldIndex, 1)[0]
				temp.splice(newIndex, 0, movedItem)
				this.list = temp
				this.$nextTick(() => this.initPositions())
			},

			// 触摸结束事件:ml-citation{ref="4,8" data="citationList"}
			handleTouchEnd() {
				this.activeIndex = -1
				this.offsetX = 0
				this.offsetY = 0
			}
		}
	}
</script>

<style>
	.container {
		padding: 10px;
		overflow: hidden;
		/* 处理浮动元素换行 */
	}

	.drag-item {
		float: left;
		width: 160px;
		height: 80px;
		margin: 8px;
		background: #fff;
		border-radius: 12px;
		display: flex;
		align-items: center;
		justify-content: center;
		transition: all 0.3s;
		user-select: none;
	}
</style>
相关推荐
艾小码21 小时前
从入门到精通:JavaScript异步编程避坑指南
前端·javascript
七度光阴;21 小时前
Web后端登录认证(会话技术)
前端·tlias智能辅助系统
菜鸟una1 天前
【微信小程序 + map组件】自定义地图气泡?原生气泡?如何抉择?
前端·vue.js·程序人生·微信小程序·小程序·typescript
昔人'1 天前
`list-style-type: decimal-leading-zero;`在有序列表`<ol></ol>` 中将零添加到一位数前面
前端·javascript·html
岁月宁静1 天前
深度定制:在 Vue 3.5 应用中集成流式 AI 写作助手的实践
前端·vue.js·人工智能
2501_915909061 天前
“绑定 HTTPS” 的工程全流程 从证书配置到真机验证与故障排查
网络协议·http·ios·小程序·https·uni-app·iphone
心易行者1 天前
10天!前端用coze,后端用Trae IDE+Claude Code从0开始构建到平台上线
前端
saadiya~1 天前
ECharts 实时数据平滑更新实践(含 WebSocket 模拟)
前端·javascript·echarts
fruge1 天前
前端三驾马车(HTML/CSS/JS)核心概念深度解析
前端·css·html
百锦再1 天前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net