# 原生小程序图片拖拽

项目是在wx-drag-image上基础上进行了一点修改

本文在 wx-drag-image的基础行了新增

使用方法

使用npm方式

1.使用拖拽功能可直接下载安装wx-drag-img (npm i wx-drag-img)
npm地址链接: wx-drag-img

自己创建Component 使用下方代码(下方代码在原作者的基础上进行了新增)

1.增加删除按钮的显隐(因为我项目需要再其他地方删除
新增的控制参数 deletable(默认为true,需要隐藏设置为false)
2.增加点击查看预览(因为需要使用wx.previewImage预览图片需要设置current的值,所以增加了点击事件获取点击的url)
新增的点击事件: givImage

index.html

<view style="width: {{containerRes.width}}px; height: {{containerRes.height}}px;" class="drag-container">
  <view wx:for="{{dragImgList}}" wx:key="id" style="transform: translate({{index === currentIndex ? tranX : item.tranX}}px, {{index === currentIndex ? tranY : item.tranY}}px); z-index: {{index === currentIndex ? 10 : 1}}; width: {{previewSize}}px; height: {{previewSize}}px;" class="drag-item drag-item-transition" mark:index="{{index}}" mark:key="{{item.key}}" catch:longpress="longPress" catch:touchmove="touchMove" catch:touchend="touchEnd" data-item="{{item}}" catch:tap="givImage">
    <image class="drag-item-img" src="{{item.src}}" />
    <view wx:if="{{deletable}}" catch:tap="deleteImg" mark:key="{{item.key}}" class="drag-item-delete">
      <view class="drag-item-delete_default" style="{{deleteStyle}}">x</view>
    </view>
  </view>
  <view bindtap="uploadImage" class="drag-item drag-upload" hidden="{{dragImgList.length >= maxCount}}" style="transform: translate({{uploadPosition.tranX}}px, {{uploadPosition.tranY}}px); width: {{previewSize}}px; height: {{previewSize}}px;">
    <view class="drag-upload_solt">
      <slot name="upload"></slot>
    </view>
    <view class="drag-upload_default"><text>+</text></view>
  </view>
</view>

index.js

Component({
	options: {
		multipleSlots: !0
	},
	properties: {
		previewSize: {
			type: Number,
			value: 100
		},
		deletable: {
		type: Boolean,
		value: true
		},
		defaultImgList: {
			type: Array,
			value: [],
			observer(t) {
				if (t?.length && !this.data.dragImgList.length) {
					const e = this.getDragImgList(t);
					this.setUploaPosition(e.length), this.setData({
						dragImgList: e
					})
				}
			}
		},
		maxCount: {
			type: Number,
			value: 9
		},
		columns: {
			type: Number,
			value: 3
		},
		gap: {
			type: Number,
			value: 9
		},
		deleteStyle: {
			type: String,
			value: ""
		}
	},
	data: {
		dragImgList: [],
		containerRes: {
			top: 0,
			left: 0,
			width: 0,
			height: 0
		},
		currentKey: -1,
		currentIndex: -1,
		tranX: 0,
		tranY: 0,
		uploadPosition: {
			tranX: 0,
			tranY: 0
		}
	},
	lifetimes: {
		ready() {
			this.createSelectorQuery().select(".drag-container").boundingClientRect((({
				top: t,
				left: e
			}) => {
				this.setData({
					"containerRes.top": t,
					"containerRes.left": e
				})
			})).exec()
		}
	},
	methods: {
		longPress(t) {
			const e = t.mark.index,
				{
					pageX: a,
					pageY: i
				} = t.touches[0],
				{
					previewSize: s,
					containerRes: {
						top: n,
						left: r
					}
				} = this.data;
			this.setData({
				currentIndex: e,
				tranX: a - s / 2 - r,
				tranY: i - s / 2 - n
			})
		},
		touchMove(t) {
			if (this.data.currentIndex < 0) return;
			const {
				pageX: e,
				pageY: a
			} = t.touches[0], {
				previewSize: i,
				containerRes: {
					top: s,
					left: n
				}
			} = this.data, r = e - i / 2 - n, o = a - i / 2 - s;
			this.setData({
				tranX: r,
				tranY: o
			});
			const h = t.mark.key,
				g = this.getMoveKey(r, o);
			h !== g && this.data.currentKey !== h && (this.data.currentKey = h, this.replace(h, g))
		},
		getMoveKey(t, e) {
			const {
				dragImgList: a,
				previewSize: i,
				columns: s
			} = this.data, n = (t, e) => {
				const a = Math.round(t / i);
				return a >= e ? e - 1 : a < 0 ? 0 : a
			}, r = s * n(e, Math.ceil(a.length / s)) + n(t, s);
			return r >= a.length ? a.length - 1 : r
		},
		replace(t, e) {
			const a = this.data.dragImgList;
			a.forEach((a => {
				t < e ? a.key > t && a.key <= e ? a.key-- : a.key === t && (a.key = e) : t > e && (a.key >= e && a.key < t ? a.key++ : a.key === t && (a.key = e))
			})), this.getListPosition(a)
		},
		getListPosition(t) {
			const {
				previewSize: e,
				columns: a,
				gap: i
			} = this.data, s = t.map((t => (t.tranX = (e + i) * (t.key % a), t.tranY = Math.floor(t.key / a) * (e + i), t)));
			this.setData({
				dragImgList: s
			}), this.updateEvent(s)
		},
		touchEnd() {
			this.setData({
				tranX: 0,
				tranY: 0,
				currentIndex: -1
			}), this.data.currentKey = -1
		},
		updateEvent(t) {
			const e = [...t].sort(((t, e) => t.key - e.key)).map((t => t.src));
			this.triggerEvent("updateImageList", {
				list: e
			})
		},
		async uploadImage() {
			let {
				dragImgList: t,
				maxCount: e
			} = this.data;
			try {
				const a = await wx.chooseMedia({
						count: e - t.length,
						mediaType: ["image"]
					}),
					i = this.getDragImgList(a?.tempFiles?.map((({
						tempFilePath: t
					}) => t)) || [], !1);
				t = t.concat(i), this.setUploaPosition(t.length), this.setData({
					dragImgList: t
				}), this.updateEvent(t)
			} catch (t) {
				console.log(t)
			}
		},
		getContainerRect(t) {
			const {
				columns: e,
				previewSize: a,
				maxCount: i,
				gap: s
			} = this.data, n = t === i ? t : t + 1, r = Math.ceil(n / e);
			return {
				width: e * a + (e - 1) * s,
				height: r * a + s * (r - 1)
			}
		},
		getDragImgList(t, e = !0) {
			let {
				dragImgList: a,
				previewSize: i,
				columns: s,
				gap: n
			} = this.data;
			return t.map(((t, r) => {
				const o = (e ? 0 : a.length) + r;
				return {
					tranX: (i + n) * (o % s),
					tranY: Math.floor(o / s) * (i + n),
					src: t,
					id: o,
					key: o
				}
			}))
		},
		setUploaPosition(t) {
			const {
				previewSize: e,
				columns: a,
				gap: i
			} = this.data, s = {
				tranX: t % a * (e + i),
				tranY: Math.floor(t / a) * (e + i)
			}, {
				width: n,
				height: r
			} = this.getContainerRect(t);
			this.setData({
				uploadPosition: s,
				"containerRes.width": n,
				"containerRes.height": r
			})
		},
		deleteImg(t) {
			const e = t.mark.key,
				a = this.data.dragImgList.filter((t => t.key !== e));
			a.forEach((t => {
				t.key > e && t.key--
			})), this.getListPosition(a), this.setUploaPosition(a.length)
		},
		givImage(e) {
			let item= e.currentTarget.dataset.item
			this.triggerEvent("giveIndex", {
				item
			})
		}
	}

});

index.wxss

.drag-container {
	position: relative;
}

.drag-item {
	position: absolute;
	top: 0;
	left: 0;
}

.drag-item-transition {
	transition: transform 0.1s
}

.drag-item-img {
	width: 100%;
	height: 100%;
	border-radius: 24rpx;
}

.drag-item-delete {
	position: absolute;
	top: 0;
	right: 0;
}

.drag-item-delete_default {
	display: flex;
	width: 21px;
	height: 15px;
	line-height: 10px;
	justify-content: center;
	background-color: rgba(0, 0, 0, 0.7);
	border-radius: 0 0 0 12px;
	color: #FEFEFE;
}

.drag-upload .drag-upload_solt:empty+.drag-upload_default {
	display: block;
	border: 2px dashed;
	width: 100%;
	height: 100%;
	box-sizing: border-box;
	text-align: center;
	font-size: 70px;
	font-weight: bold;
	line-height: 100%;
}

.drag-upload .drag-upload_default {
	display: none;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值