Parcourir la source

拖动效果bug修改

郭宇琦 il y a 2 semaines
Parent
commit
fac736c9e0
1 fichiers modifiés avec 355 ajouts et 344 suppressions
  1. 355 344
      components/basic-drag/index.vue

+ 355 - 344
components/basic-drag/index.vue

@@ -1,29 +1,18 @@
 <template>
 	<movable-area :style="[getAreaStyle]">
-		<movable-view
-			v-for="(item, index) in list"
-			:animation="animation"
-			:direction="direction"
-			:key="item.key"
-			:damping="damping"
-			:x="item.x"
-			:y="item.y"
-			:disabled="longpress ? disabled : false"
-			@longpress="handleLongpress"
-			@touchstart="handleDragStart(index)"
-			@change="handleMoving"
-			@touchend="handleDragEnd"
-			:style="[getViewStyle]"
-			class="base-drag-wrapper"
-			:class="{ active: activeIndex === index }"
-		>
-			
+		<movable-view v-for="(item, index) in list" :animation="animation" :direction="direction" :key="item.key"
+			:damping="damping" :x="item.x" :y="item.y" :disabled="longpress ? disabled : false"
+			@longpress="handleLongpress" @touchstart="handleDragStart(index)" @change="handleMoving"
+			@touchend="handleDragEnd" :style="[getViewStyle]" class="base-drag-wrapper"
+			:class="{ active: activeIndex === index }">
+
 			<view class="drag-item">
-				<view @longpress="toggleEdit" :class="['tab-item']"  >
-				  <image v-if="item.isLock" :src="icons.lock" class="right-icon" />
-				  <image  v-if="!item.isLock && isActiveEdit"  @click="deleteTab(item)"  :src="icons.edit" class="right-icon" />
-				  <image :src="item.iconUrl" class="icon" />
-				  <view>{{ item.name }}</view>
+				<view @longpress="toggleEdit" :class="['tab-item']">
+					<image v-if="item.isLock" :src="icons.lock" class="right-icon" />
+					<image v-if="!item.isLock && isActiveEdit" @click="deleteTab(item)" :src="icons.edit"
+						class="right-icon" />
+					<image :src="item.iconUrl" class="icon" />
+					<view>{{ item.name }}</view>
 				</view>
 			</view>
 		</movable-view>
@@ -31,255 +20,272 @@
 </template>
 
 <script>
-	import { QINIU_URL } from '@/common/constant'
+	import {
+		QINIU_URL
+	} from '@/common/constant'
 	const ICONS = {
-	  lock: `${QINIU_URL}FgMCTZCySvEgLYgkzU65BUR4f4Ls`,
-	  edit: `${QINIU_URL}Fq3V1Zi5tKH7ibTwG1nO7N96CU8m`,
-	  add: `${QINIU_URL}FqLEWbMe8DcnQtNz6GdDDD87ObZK`,
-	  placeholder: `${QINIU_URL}FpKvfFNSDbx0d9RDwyGAQdFb7Kt6`
+		lock: `${QINIU_URL}FgMCTZCySvEgLYgkzU65BUR4f4Ls`,
+		edit: `${QINIU_URL}Fq3V1Zi5tKH7ibTwG1nO7N96CU8m`,
+		add: `${QINIU_URL}FqLEWbMe8DcnQtNz6GdDDD87ObZK`,
+		placeholder: `${QINIU_URL}FpKvfFNSDbx0d9RDwyGAQdFb7Kt6`
 	}
-	
-export default {
-	props: {
-		column: {
-			type: Number,
-			default: 3
-		},
-		value: {
-			type: Array,
-			default: () => []
-		},
-		width: {
-			type: Number,
-			default: 375
-		},
-		height: {
-			type: String,
-			default: '100px'
-		},
-		itemKey: {
-			type: String,
-			required: true
-		},
-		itemHeight: {
-			type: String,
-			default: '100px'
-		},
-		direction: {
-			type: String,
-			default: 'all',
-			validator: value => {
-				return ['all', 'vertical', 'horizontal', 'none'].includes(value);
+
+	export default {
+		props: {
+			column: {
+				type: Number,
+				default: 3
+			},
+			value: {
+				type: Array,
+				default: () => []
+			},
+			width: {
+				type: Number,
+				default: 375
+			},
+			height: {
+				type: String,
+				default: '100px'
+			},
+			itemKey: {
+				type: String,
+				required: true
+			},
+			itemHeight: {
+				type: String,
+				default: '100px'
+			},
+			direction: {
+				type: String,
+				default: 'all',
+				validator: value => {
+					return ['all', 'vertical', 'horizontal', 'none'].includes(value);
+				}
+			},
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			damping: {
+				type: Number,
+				default: 20
+			},
+			longpress: {
+				type: Boolean,
+				default: true
 			}
 		},
-		animation: {
-			type: Boolean,
-			default: true
+		data() {
+			const MAX_TAB_LEN = 4
+			return {
+				QINIU_URL,
+				MAX_TAB_LEN,
+				icons: ICONS,
+				isActiveEdit: false,
+				placeholderTab: {
+					name: '',
+					icon: ICONS.placeholder,
+					isLock: false,
+					isPlaceholder: true
+				},
+				list: [],
+				disabled: true,
+				activeIndex: -1,
+				moveToIndex: -1,
+				oldIndex: -1,
+				tempDragInfo: {
+					x: '',
+					y: ''
+				},
+				cloneList: []
+			};
 		},
-		damping: {
-			type: Number,
-			default: 20
-		},
-		longpress: {
-			type: Boolean,
-			default: true
-		}
-	},
-	data() {
-		const MAX_TAB_LEN = 4
-		return {
-		  QINIU_URL,
-		  MAX_TAB_LEN,
-		  icons: ICONS,
-		  isActiveEdit: false,
-		  placeholderTab: {
-		    name: '',
-		    icon: ICONS.placeholder,
-		    isLock: false,
-		    isPlaceholder: true
-		  },
-			list: [],
-			disabled: true,
-			activeIndex: -1,
-			moveToIndex: -1,
-			oldIndex: -1,
-			tempDragInfo: {
-				x: '',
-				y: ''
+		computed: {
+			getAreaStyle() {
+				const width = this.getRealWidth(this.width);
+				return {
+					width: width + 'px',
+					height: this.height !== 'auto' ? this.height : Math.round(this.list.length / this.column) * this
+						.getItemHeight + 'px'
+				};
 			},
-			cloneList: []
-		};
-	},
-	computed: {
-		getAreaStyle() {
-			const width = this.getRealWidth(this.width);
-			return { width: width + 'px', height: this.height !== 'auto' ? this.height : Math.round(this.list.length / this.column) * this.getItemHeight + 'px' };
-		},
-		getViewStyle() {
-			const { itemHeight, getItemWidth } = this;
-			return { width: getItemWidth + 'px', height: itemHeight };
-		},
-		getItemHeight() {
-			return parseFloat(this.itemHeight);
-		},
-		getItemWidth() {
-			if (this.column === 0) return;
-			const width = this.getRealWidth(this.width);
-			return (parseFloat(width) / this.column).toFixed(2);
-		}
-	},
-	methods: {
-		getMovableItem(tab) {
-		  return this.isActiveEdit && !tab.isLock && !tab.isPlaceholder
-		},
-		deleteTab(tab) {
-		  if (tab.isLock) return
-		  const index = this.list.findIndex(t => t.name === tab.name)
-		  if (index !== -1) {
-		    const removedTab = this.list.splice(index, 1)[0]
-			this.cloneList.splice(index,1)
-			this.initList(this.cloneList);
-			const endList = this.list.map(item => this.omit(item, ['x', 'y', 'key']));
-			this.$emit('end', this.list,removedTab);
-		  }
-		},
-		addPlaceholders() {
-		  while (this.list.length < this.MAX_TAB_LEN) {
-		    this.list.push({ ...this.placeholderTab })
-		  }
-		},
-		toggleEdit(e) {
-		  this.isActiveEdit = !this.isActiveEdit
-		  this.$emit('toggleEdit', this.isActiveEdit);
-		},
-		//获取实际的宽度
-		getRealWidth(width) {
-			let pxValue = uni.upx2px(width);
-			// console.log(pxValue)
-			// if (width.includes('%')) {
-			// 	const windowWidth = uni.getSystemInfoSync().windowWidth;
-			// 	width = windowWidth * (parseFloat(width) / 100);
-			// }
-			return pxValue;
-		},
-
-		initList(list = []) {
-			const newList = this.deepCopy(list);
-			this.list = newList.map((item, index) => {
-				const [x, y] = this.getPosition(index);
+			getViewStyle() {
+				const {
+					itemHeight,
+					getItemWidth
+				} = this;
 				return {
-					...item,
-					x,
-					y,
-					key: Math.random() + index
+					width: getItemWidth + 'px',
+					height: itemHeight
 				};
-			});
-			this.cloneList = this.deepCopy(this.list);
+			},
+			getItemHeight() {
+				return parseFloat(this.itemHeight);
+			},
+			getItemWidth() {
+				if (this.column === 0) return;
+				const width = this.getRealWidth(this.width);
+				return (parseFloat(width) / this.column).toFixed(2);
+			}
 		},
+		methods: {
+			getMovableItem(tab) {
+				return this.isActiveEdit && !tab.isLock && !tab.isPlaceholder
+			},
+			deleteTab(tab) {
+				if (tab.isLock) return
+				const index = this.list.findIndex(t => t.name === tab.name)
+				if (index !== -1) {
+					const removedTab = this.list.splice(index, 1)[0]
+					this.cloneList.splice(index, 1)
+					this.initList(this.cloneList);
+					const endList = this.list.map(item => this.omit(item, ['x', 'y', 'key']));
+					this.$emit('end', this.list, removedTab);
+				}
+			},
+			addPlaceholders() {
+				while (this.list.length < this.MAX_TAB_LEN) {
+					this.list.push({
+						...this.placeholderTab
+					})
+				}
+			},
+			toggleEdit(e) {
+				this.isActiveEdit = !this.isActiveEdit
+				this.$emit('toggleEdit', this.isActiveEdit);
+			},
+			//获取实际的宽度
+			getRealWidth(width) {
+				let pxValue = uni.upx2px(width);
+				// console.log(pxValue)
+				// if (width.includes('%')) {
+				// 	const windowWidth = uni.getSystemInfoSync().windowWidth;
+				// 	width = windowWidth * (parseFloat(width) / 100);
+				// }
+				return pxValue;
+			},
 
-		//长按
-		handleLongpress(index) {
-			this.disabled = false;
-		},
+			initList(list = []) {
+				const newList = this.deepCopy(list);
+				this.list = newList.map((item, index) => {
+					const [x, y] = this.getPosition(index);
+					return {
+						...item,
+						x,
+						y,
+						key: Math.random() + index
+					};
+				});
+				this.cloneList = this.deepCopy(this.list);
+			},
 
-		//拖拽开始
-		handleDragStart(index) {
-			this.activeIndex = index;
-			this.oldIndex = index;
-		},
+			//长按
+			handleLongpress(index) {
+				this.disabled = false;
+			},
 
-		//拖拽中
-		handleMoving(e) {
-			if (e.detail.source !== 'touch') return;
-			const { x, y } = e.detail;
-			Object.assign(this.tempDragInfo, { x, y });
-			const currentX = Math.floor((x + this.getItemWidth / 2) / this.getItemWidth);
-			const currentY = Math.floor((y + this.getItemHeight / 2) / this.getItemHeight);
-			
-			this.moveToIndex = Math.min(currentY * this.column + currentX, this.list.length - 1);
-			
-			if (this.oldIndex !== this.moveToIndex && this.oldIndex !== -1 && this.moveToIndex !== -1) {
-				const newList = this.deepCopy(this.cloneList);
-				newList.splice(this.moveToIndex, 0, ...newList.splice(this.activeIndex, 1));
-			
-				this.list.forEach((item, index) => {
-					if (index !== this.activeIndex) {
-						const itemIndex = newList.findIndex(val => val[this.itemKey] === item[this.itemKey]);
-						[item.x, item.y] = this.getPosition(itemIndex);
-					}
+			//拖拽开始
+			handleDragStart(index) {
+				this.activeIndex = index;
+				this.oldIndex = index;
+			},
+
+			//拖拽中
+			handleMoving(e) {
+				if (e.detail.source !== 'touch') return;
+				const {
+					x,
+					y
+				} = e.detail;
+				Object.assign(this.tempDragInfo, {
+					x,
+					y
 				});
-				this.oldIndex = this.moveToIndex;
-			}
-			
-		},
+				const currentX = Math.floor((x + this.getItemWidth / 2) / this.getItemWidth);
+				const currentY = Math.floor((y + this.getItemHeight / 2) / this.getItemHeight);
 
-		//获取当前的位置
-		getPosition(index) {
-			const x = (index % this.column) * this.getItemWidth;
-			const y = Math.floor(index / this.column) * this.getItemHeight;
-			return [x, y];
-		},
+				this.moveToIndex = Math.min(currentY * this.column + currentX, this.list.length - 1);
 
-		//拖拽结束
-		handleDragEnd(e) {
-			if (this.disabled) return;
-			if (this.moveToIndex !== -1 && this.activeIndex !== -1 && this.moveToIndex !== this.activeIndex) {
-				this.cloneList.splice(this.moveToIndex, 0, ...this.cloneList.splice(this.activeIndex, 1));
-			} else {
-				this.$set(this.list[this.activeIndex], 'x', this.tempDragInfo.x);
-				this.$set(this.list[this.activeIndex], 'y', this.tempDragInfo.y);
-			}
-			this.initList(this.cloneList);
-			const endList = this.list.map(item => this.omit(item, ['x', 'y', 'key']));
-			this.$emit('input', endList);
-			this.$emit('end', endList);
-			this.activeIndex = -1;
-			this.oldIndex = -1;
-			this.moveToIndex = -1;
-			this.disabled = true;
-		},
+				if (this.oldIndex !== this.moveToIndex && this.oldIndex !== -1 && this.moveToIndex !== -1) {
+					const newList = this.deepCopy(this.cloneList);
+					newList.splice(this.moveToIndex, 0, ...newList.splice(this.activeIndex, 1));
 
-		deepCopy(source) {
-			return JSON.parse(JSON.stringify(source));
-		},
+					this.list.forEach((item, index) => {
+						if (index !== this.activeIndex) {
+							const itemIndex = newList.findIndex(val => val[this.itemKey] === item[this.itemKey]);
+							[item.x, item.y] = this.getPosition(itemIndex);
+						}
+					});
+					this.oldIndex = this.moveToIndex;
+				}
+
+			},
+
+			//获取当前的位置
+			getPosition(index) {
+				const x = (index % this.column) * this.getItemWidth;
+				const y = Math.floor(index / this.column) * this.getItemHeight;
+				return [x, y];
+			},
 
-		/**
-		 * 排除掉obj里面的key值
-		 * @param {object} obj
-		 * @param {Array|string} args
-		 * @returns {object}
-		 */
-		omit(obj, args) {
-			
-			if (!args) return obj;
-			const newObj = {};
-			const isString = typeof args === 'string';
-			const keys = Object.keys(obj).filter(item => {
-				if (isString) {
-					return item !== args;
+			//拖拽结束
+			handleDragEnd(e) {
+				if (this.disabled) return;
+				if (this.moveToIndex !== -1 && this.activeIndex !== -1 && this.moveToIndex !== this.activeIndex) {
+					this.cloneList.splice(this.moveToIndex, 0, ...this.cloneList.splice(this.activeIndex, 1));
+				} else {
+					this.$set(this.list[this.activeIndex], 'x', this.tempDragInfo.x);
+					this.$set(this.list[this.activeIndex], 'y', this.tempDragInfo.y);
 				}
-				return !args.includes(item);
-			});
+				this.initList(this.cloneList);
+				const endList = this.list.map(item => this.omit(item, ['x', 'y', 'key']));
+				this.$emit('input', endList);
+				this.$emit('end', endList);
+				this.activeIndex = -1;
+				this.oldIndex = -1;
+				this.moveToIndex = -1;
+				this.disabled = true;
+			},
+
+			deepCopy(source) {
+				return JSON.parse(JSON.stringify(source));
+			},
+
+			/**
+			 * 排除掉obj里面的key值
+			 * @param {object} obj
+			 * @param {Array|string} args
+			 * @returns {object}
+			 */
+			omit(obj, args) {
 
-			keys.forEach(key => {
-				if (obj[key] !== undefined) newObj[key] = obj[key];
-			});
-			return newObj;
+				if (!args) return obj;
+				const newObj = {};
+				const isString = typeof args === 'string';
+				const keys = Object.keys(obj).filter(item => {
+					if (isString) {
+						return item !== args;
+					}
+					return !args.includes(item);
+				});
+
+				keys.forEach(key => {
+					if (obj[key] !== undefined) newObj[key] = obj[key];
+				});
+				return newObj;
+			}
+		},
+		watch: {
+			value: {
+				handler() {
+					this.initList(this.value);
+				},
+				immediate: true,
+				deep: true
+			}
 		}
-	},
-	mounted() {
-		this.initList(this.value);
-	},
-	watch: {
-		// value: {
-		// 	handler() {
-		// 		this.initList(this.value);
-		// 	},
-		// 	immediate: true,
-		// 	deep: true
-		// }
-	}
-};
+	};
 </script>
 
 <style lang="scss" scoped>
@@ -288,101 +294,106 @@ export default {
 		display: flex;
 		align-items: center;
 		justify-content: center;
+
 		.tab-item {
-		  text-align: center;
-		  width: 100%;
-		  position: relative;
-		  margin-top: 24rpx;
-		  height: 100px;
-		  .right-icon {
-		    position: absolute;
-		    right: 20rpx;
-		    top: 0;
-		    width: 40rpx;
-		    height: 40rpx;
-		    z-index: 9;
-		  }
-		
-		  .icon {
-		    width: 112rpx;
-		    height: 112rpx;
-		    margin-bottom: 20rpx;
-		  }
-		
-		  .name {
-		    font-size: 28rpx;
-		    color: #060809;
-		
-		    &.shake {
-		      animation: shake 0.2s ease-in-out infinite;
-		    }
-		  }
+			text-align: center;
+			width: 100%;
+			position: relative;
+			margin-top: 24rpx;
+			height: 100px;
+
+			.right-icon {
+				position: absolute;
+				right: 20rpx;
+				top: 0;
+				width: 40rpx;
+				height: 40rpx;
+				z-index: 9;
+			}
+
+			.icon {
+				width: 112rpx;
+				height: 112rpx;
+				margin-bottom: 20rpx;
+			}
+
+			.name {
+				font-size: 28rpx;
+				color: #060809;
+
+				&.shake {
+					animation: shake 0.2s ease-in-out infinite;
+				}
+			}
 		}
-		
-		
+
+
 	}
-.base-drag-wrapper {
-	opacity: 1;
-	z-index: 1;
-	&.active {
-		opacity: 0.7;
-		transform: scale(1.3);
-		z-index: 99;
+
+	.base-drag-wrapper {
+		opacity: 1;
+		z-index: 1;
+
+		&.active {
+			opacity: 0.7;
+			transform: scale(1.3);
+			z-index: 99;
+		}
 	}
-}
 </style>
 <style lang="scss" scoped>
-@import "@/libs/css/layout.scss";
-    .title {
-      font-family: PingFangSC, PingFang SC;
-      font-weight: 400;
-      font-size: 36rpx;
-      color: #060809;
-      margin-bottom: 16rpx;
-      padding-left: 40rpx;
-
-      .sort-num {
-        margin-left: 12rpx;
-        width: 36rpx;
-        font-family: Futura, Futura;
-        font-size: 30rpx;
-        color: #060809;
-      }
-    }
-
-    .tab-item-container {
-      display: flex;
-
-      &.is-to-be-select {
-        flex-wrap: wrap;
-      }
-    }
-
-
-  .tips {
-    font-size: 24rpx;
-    color: #060809;
-    text-align: center;
-    margin-top: 32rpx;
-  }
-
-  .un-bind-btn {
-    position: absolute;
-    bottom: 56rpx;
-    left: 50%;
-    transform: translateX(-50%);
-    width: 93%;
-    padding: 24rpx;
-    text-align: center;
-    background: #E4E7EC;
-    border-radius: 40rpx;
-    font-family: PingFangSC, PingFang SC;
-    font-weight: bold;
-    font-size: 32rpx;
-    color: #060809;
-
-    &:active {
-      opacity: .7;
-    }
-  }
-</style>
+	@import "@/libs/css/layout.scss";
+
+	.title {
+		font-family: PingFangSC, PingFang SC;
+		font-weight: 400;
+		font-size: 36rpx;
+		color: #060809;
+		margin-bottom: 16rpx;
+		padding-left: 40rpx;
+
+		.sort-num {
+			margin-left: 12rpx;
+			width: 36rpx;
+			font-family: Futura, Futura;
+			font-size: 30rpx;
+			color: #060809;
+		}
+	}
+
+	.tab-item-container {
+		display: flex;
+
+		&.is-to-be-select {
+			flex-wrap: wrap;
+		}
+	}
+
+
+	.tips {
+		font-size: 24rpx;
+		color: #060809;
+		text-align: center;
+		margin-top: 32rpx;
+	}
+
+	.un-bind-btn {
+		position: absolute;
+		bottom: 56rpx;
+		left: 50%;
+		transform: translateX(-50%);
+		width: 93%;
+		padding: 24rpx;
+		text-align: center;
+		background: #E4E7EC;
+		border-radius: 40rpx;
+		font-family: PingFangSC, PingFang SC;
+		font-weight: bold;
+		font-size: 32rpx;
+		color: #060809;
+
+		&:active {
+			opacity: .7;
+		}
+	}
+</style>