图例:
1.先创建组件取名:van-dragImgList
2.组件代码:
wxml:
<view class="drag-container" id="drag-container" style="height: {{imgItemHeight}}px;">
<view
wx:for="{{dragImgList}}"
wx:key="index"
style="transform: translate({{index === currentIndex ? tranX : item.tranX}}px, {{index === currentIndex ? tranY : item.tranY}}px); z-index: {{index === currentIndex ? 10 : 1}};height: {{ITEM_SIZE}}px;"
class="darg-item item-transition"
mark:index="{{index}}"
mark:key="{{item.key}}"
catch:longpress="longPress"
catch:touchmove="touchMove"
catch:touchend="touchEnd"
>
<image class="darg-item-img" mode="aspectFill" src="{{item.src}}" data-index="{{index}}" bindtap="previewImage"/>
<view catch:tap="deleteImg" mark:key="{{item.key}}" class="drag-item-delete"><van-icon name="cross" /></view>
</view>
<view
bindtap="uploadImage"
class="darg-item drag-item-upload"
hidden="{{dragImgList.length >= 18}}"
style="transform: translate({{uploadPosition.tranX}}px, {{uploadPosition.tranY}}px); height: {{ITEM_SIZE}}px;"
>
<van-icon wx:if="{{ITEM_SIZE}}" class="iconfont icon-mn_shangchuantupian_fill" class-prefix="icon" name="icon-mn_shangchuantupian_fill" size="80rpx"></van-icon>
</view>
</view>
wxss:
.drag-container{
position: relative;
}
.item-transition {
transition: transform 0.1s
}
.darg-item{
position: absolute;
top: 0;
left: 0;
/* width: 100px; */
/* height: 100px; */
width: calc(100% / 3);
height: calc(100% / 3);
}
.darg-item-img{
width: 100%;
height: 100%;
border:2rpx solid #ffffff;
box-sizing: border-box;
/* position: absolute; */
object-fit: cover;
/* left:50%;
top:0;
transform: translate(-50%,0); */
}
.drag-item-delete{
position: absolute;
top: 2rpx;
right: 2rpx;
width: 33rpx;
height: 33rpx;
background-color: rgba(0,0,0,0.5);
font-size: 35rpx;
line-height: 28rpx;
text-align: center;
border-radius: 8rpx;
/* border-radius: 0 0 0 64rpx; */
color: #fff;
}
.drag-item-upload{
background-color: #f7f7f7;
/* font-size: 200rpx; */
text-align: center;
color: white;
/* line-height: 150rpx; */
border: 2rpx solid #ffffff;
box-sizing: border-box;
position: relative;
}
.iconfont {
font-size: 80rpx;
color: #acacac;
margin-top: 72rpx;
}
json:
{
"component": true,
"usingComponents": {}
}
js:
Component({
/**
* 组件的属性列表
*/
properties: {
data: {
type: Array,
value: []
},
isPreviewMode: {
type: Boolean,
value: false
},
dataIntroPicsProps:{
type: Array,
value: []
}
},
observers: {
dataIntroPicsProps: function(dataIntroPics) {
console.log(dataIntroPics,'图文传过去的数据!!!');
if(dataIntroPics){
this.setData({
dragImgList: dataIntroPics
});
console.log(4444444444,this.data.dragImgList)
}
}
},
/**
* 组件的初始数据
*/
data: {
ITEM_SIZE: 0, // 图片大小 单位px
dragImgList: [], // 图片列表 { src: string, key: number, tranX: number, tranY: number }[]
containerRes: {}, // 拖拽容器属性
currentKey: -1, // 正在拖拽图片的key
currentIndex: -1, // 正在拖拽图片的index
tranX: 0, // 正在拖拽图片移动的x距离
tranY: 0, // 正在拖拽图片移动的y距离
uploadPosition: { // upload上传图标位移距离
tranX: 0,
tranY: 0,
},
imgItemHeight:0,
},
lifetimes: {
ready() {
this.createSelectorQuery()
.select(".drag-container")
.boundingClientRect((res) => {
this.data.containerRes = res
console.log('宽度111:', res);
this.setData({
containerRes:res,
ITEM_SIZE:res.width/3,
imgItemHeight:res.width/3
})
// ============================= 还原上传的位置
// 修改剩余图片位置
this.getListPosition(this.data.dragImgList)
// 修改上传图标位置
this.setUploaPosition(this.data.dragImgList.length)
this.getDragImgListHeight();
}).exec();
}
},
/**
* 组件的方法列表
*/
methods: {
uploadImage() {
let that = this;
let { dragImgList, ITEM_SIZE } = that.data
wx.chooseImage({
count: 9 - dragImgList.length,
success: (res) => {
const imgList = res.tempFilePaths.map((item, index) => ({
tranX: ITEM_SIZE * ((dragImgList.length + index) % 3),
tranY: Math.floor((dragImgList.length + index) / 3) * ITEM_SIZE,
src: item,
key: dragImgList.length + index
}))
dragImgList = dragImgList.concat(imgList)
// 修改上传图标位置
that.setUploaPosition(dragImgList.length)
that.setData({
dragImgList,
})
that.getListPosition(dragImgList)
that.getDragImgListHeight();
}
})
},
getDragImgListHeight(){
let dragImgList = this.data.dragImgList;
let ITEM_SIZE_H = this.data.ITEM_SIZE;
if(dragImgList.length<3){
this.setData({
imgItemHeight:ITEM_SIZE_H
})
}else if(dragImgList.length>2 && dragImgList.length<6){
this.setData({
imgItemHeight:ITEM_SIZE_H*2
})
}else if(dragImgList.length>5 && dragImgList.length<9){
this.setData({
imgItemHeight:ITEM_SIZE_H*3
})
}else if(dragImgList.length>8 && dragImgList.length<12){
this.setData({
imgItemHeight:ITEM_SIZE_H*4
})
}else if(dragImgList.length>11 && dragImgList.length<15){
this.setData({
imgItemHeight:ITEM_SIZE_H*5
})
}else if(dragImgList.length>14 && dragImgList.length<19){
this.setData({
imgItemHeight:ITEM_SIZE_H*6
})
}
},
setUploaPosition(listLength) {
const ITEM_SIZE = this.data.ITEM_SIZE
const uploadPosition = {
tranX: listLength % 3 * ITEM_SIZE,
tranY: Math.floor(listLength / 3) * ITEM_SIZE,
}
this.setData({
uploadPosition,
})
},
deleteImg(e) {
console.log(e,444777888);
const key = e.mark.key
// 删除图片
const list = this.data.dragImgList.filter((item) => item.key !== key)
// 修改key值
list.forEach((item) => item.key > key && item.key--)
// 修改剩余图片位置
this.getListPosition(list)
// 修改上传图标位置
this.setUploaPosition(list.length)
this.getDragImgListHeight();
},
getListPosition(list) {
const ITEM_SIZE = this.data.ITEM_SIZE
const dragImgList = list.map((item) => {
item.tranX = ITEM_SIZE * (item.key % 3);
item.tranY = Math.floor(item.key / 3) * ITEM_SIZE;
return item
})
this.setData({
dragImgList,
})
// 向页面传递最新图片列表
const urlList = [...dragImgList].sort((a, b) => a.key - b.key).map((item) => item.src)
this.triggerEvent('updateImage', {
list: urlList,
dragImgList:JSON.stringify(dragImgList)
})
},
//
longPress(e) {
const index = e.mark.index
const { pageX, pageY } = e.touches[0]
const { top, left } = this.data.containerRes
this.setData({
currentIndex: index,
tranX: pageX - 50 - left,
tranY: pageY - 50 - top
})
},
touchMove(e) {
// 如果currentIndex < 0,说明并没有触发longPress
if (this.data.currentIndex < 0) return
const { pageX, pageY } = e.touches[0]
const { top, left } = this.data.containerRes
const tranX = pageX - 50 - left
const tranY = pageY - 50 - top
this.setData({
tranX,
tranY
})
// 对比当前移动的key和停放位置的key,如果不一样就修改位置
const currentKey = e.mark.key
const moveKey = this.getMoveKey(tranX, tranY)
if (currentKey === moveKey || this.data.currentKey === currentKey) return
this.data.currentKey = currentKey
this.insert(currentKey, moveKey)
},
getMoveKey(tranX, tranY) {
const { dragImgList: list, ITEM_SIZE } = this.data
const _getPositionNumber = (position) => {
const positionNumber = Math.round(position/ ITEM_SIZE)
return positionNumber > 2 ? 2 : positionNumber < 0 ? 0 : positionNumber
}
const endKey = 6 * _getPositionNumber(tranY) + _getPositionNumber(tranX)
return endKey >= list.length ? list.length - 1 : endKey
},
insert(origin, end) {
const dragImgList = this.data.dragImgList
dragImgList.forEach((item) => {
if (origin < end) {
// 如果起始key小于结束key,就把区间内的key全部减一
if (item.key > origin && item.key <= end) item.key--
else if (item.key === origin) item.key = end
} else if (origin > end) {
// 如果起始key大于结束key,就把区间内的key全部加一
if (item.key >= end && item.key < origin) item.key++
else if (item.key === origin) item.key = end
}
})
this.getListPosition(dragImgList)
},
touchEnd() {
this.setData({
tranX: 0,
tranY: 0,
currentIndex: -1,
})
this.data.currentKey = -1
this.getDragImgListHeight();
},
previewImage(e){
// 获取数据索引
let that = this;
const index = e.currentTarget.dataset.index;
let dragImgListurls = [];
for(let i=0;i<that.data.dragImgList.length;i++){
dragImgListurls.push(that.data.dragImgList[i].src);
}
console.log(dragImgListurls);
wx.previewImage({
current: that.data.dragImgList[index].src, // 当前显示的图片链接
urls: dragImgListurls// 需要预览的图片链接列表
})
},
},
})
以上就是主要组件模块! 接下来就是要使用这个组件
在app.json里面全局引入:
"usingComponents": {"van-dragImgList": "./pages/app/components/dragImgList/index",}
页面中使用:
wxml:
<van-dragImgList bind:updateImage="updateImage" dataIntroPicsProps="{{dataIntroPics}}"></van-dragImgList>
注意:updateImage 方法,是组件内部上传图片,把图片数据或者其他需要的数据传给当前使用组件的页面;dataIntroPics是当前页面给组件内部传数据(当前传的数据是内部反显图片的数据用的)
js:
updateImage(e) {
console.log(e,'组建999')
this.parentMethod(e.detail);
},
parentMethod(data) {
// 主页面的方法
console.log('Parent method called with data:', data);
this.setData({
['params.mediaResources']:data.list,
['params.pageConfig']:data.dragImgList
})
},
注意:
['params.mediaResources']:data.list,
['params.pageConfig']:data.dragImgList
就是当前页面接受组件传过来的数据;
目前我的组件是根据公司需求支持18张图的;你们可以根据需求修改代码。