在编写类似发布朋友圈功能的功能时,需要实现图片的拖拽排序,删除图片等功能。
一、效果展示
**博主的小程序首页也采用了该示例代码,可以在威信中搜索:
我的百宝工具箱
二、示例代码
1.1、在自己的小程序中创建组件
1.2、组件源码
-
wxml代码
bash<view 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"> <image class="drag-item-img" src="{{item.src}}" mode="aspectFill"/> <view 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;"> <text>+</text> </view> </view>
-
wxss代码
css.drag-container { position: relative; left: 30rpx; top: 20rpx; } .drag-item { position: absolute; top: 0; left: 0; } .drag-item-transition { transition: transform 0.1s } .drag-item-img { width: 100%; height: 100%; } .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 { display: flex; justify-content: center; align-items: center; border: 2px dashed silver; width: 100%; height: 100%; box-sizing: border-box; font-size: 70px; } .drag-upload text{ margin-top: -20%; color: silver; }
-
js代码
jsComponent({ properties: { // 每个格子的大小 100*100 previewSize: { type: Number, value: 100 }, // 默认图片列表 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) } } });
-
json代码
bash{ "component": true, "usingComponents":{} }
1.3、在自己的小程序中新建page
1.4、新建page的源码
-
wxml代码
bash<view> <wxDragImg defaultImgList="{{imgList}}" previewSize="{{120}}" maxCount="{{9}}" columns="{{3}}" gap="{{10}}" bind:updateImageList="updateImageList"> </wxDragImg> </view>
-
js代码
jsPage({ data: { imgList: [] }, onLoad() {}, updateImageList(e) { console.log(e) } })
-
json代码
bash{ "usingComponents": { "wxDragImg": "../wx-drag-img" } }