微信小程序实现图片拖拽切换位置

一、实现效果

在这里插入图片描述

二、实现代码

所用到组件
movable-area movable-view

HTML

<movable-area class="areaBlock">
    <view class="picList">
        <view class="picRelative" wx:for="{{picList}}" bind:longpress="showMoveBlock" bind:touchend="hideMoveBlock" data-index="{{index}}">
            // 占位图
            <image class="dynamicImg" src="{{item.tempFilePath}}" mode="aspectFill" lazy-load="false" binderror="" bindload=""></image>
            <image class="deleteImg" wx:if="{{picList.length !== 0}}" catchtap="deleteImg" src="/images/function/deleteImg.png" mode="scaleToFill" lazy-load="false" binderror="" bindload="" data-index="{{index}}" />
            // 移动模块
            <movable-view wx:if="{{!moveIng}}" class="areaMove" bindchange="bindchange" direction="all" damping="30" x="{{defaultX}}" y="{{defaultY}}" disabled="{{currentTouchIndex === index ? false : true}}" style="z-index: {{currentTouchIndex === index ? '3' : '1'}}">
                <image class="{{currentTouchIndex === index ? 'areaImg' : ''}}" bindtap="previewImg" data-index="{{index}}" src="{{item.tempFilePath}}" mode="aspectFill" lazy-load="false" binderror="" bindload="" />
            </movable-view>
        </view>
    </view>
</movable-area>

JS

  data: {
    currentTouchIndex: -1,
    currentX: 0,
    currentY: 0,
    defaultX: 0,
    defaultY: 0,
    moveIng: false
  },
  methods: {
    // 显示底层可移动模块
    showMoveBlock(e){
      const { index } = e.currentTarget.dataset
      this.setData({
        currentTouchIndex: index
      })
    },
    // 滑动结束(判断滑块当前位置)
    hideMoveBlock(e){
      if(this.data.currentTouchIndex === -1){
        return
      }
      const { index } = e.currentTarget.dataset
      const boundary = 20
      // 判断图片移动位置
      const directionX = this.data.currentX < 0 ? 'left' : 'right'
      const directionY = this.data.currentY < 0 ? 'top' : 'bottom'
      const currentX = Math.abs(this.data.currentX)
      const currentY = Math.abs(this.data.currentY)
      // 判断是否需要交换位置
      const needChangeFlag = (currentX % 96) - (Math.floor(currentX / 96) * 40) > boundary || (currentY % 96) - (Math.floor(currentY / 96) * 40) > boundary ? false : true
      if(!needChangeFlag || (currentX < 20 && currentY < 20)){
        this.setData({
          defaultX: 0,
          defaultY: 0
        })
      }else{
        this.setData({
          moveIng: true
        })
        const moveX = directionX === 'left' ? -Math.floor(currentX / 96) : Math.floor(currentX / 96)
        const moveY = directionY === 'top' ? -Math.floor(currentY / 96) : Math.floor(currentY / 96)
        let middleCount = 0
        let changeIndex = -1
        // 根据移动方向和个数获取移动后的index(3为一行数量)
        if(Math.abs(moveY) > 1){
          middleCount = 3 * (Math.abs(moveY) - 1)
        }
        if(Math.abs(moveY) === 0){
          changeIndex = index + moveX
        }else{
          changeIndex = moveY < 0 ? index - (3 - moveX) - middleCount : index + (3 + moveX) + middleCount
        }
        this.exchangePosition(index,changeIndex)
      }
      setTimeout(()=>{
        this.setData({
          moveIng: false,
          currentTouchIndex: -1
        })
      },300)
    },
    // 图片数组交换位置
    exchangePosition(initIndex,changeIndex){
      if(changeIndex > this.data.picList.length - 1){
        return
      }
      let initPicList = this.data.picList
      const before = this.data.picList[initIndex]
      const after = this.data.picList[changeIndex]
      initPicList[initIndex] = after
      initPicList[changeIndex] = before
      this.setData({
        picList: initPicList,
        defaultX: 0,
        defaultY: 0,
      })
    },
    // 获取滑动移动的xy
    bindchange: throttle(function (e){
      this.setData({
        currentX: Math.floor(e.detail.x),
        currentY: Math.floor(e.detail.y)
      })
    },150),
    // 删除图片
    deleteImg(e){
      const indexs = e.currentTarget.dataset.index
      const picList = this.data.picList
      const picUrlList = this.data.picUrlList
      picList.splice(indexs,1)
      picUrlList.splice(indexs,1)
      this.setData({
        picList,
        picUrlList
      })
    },
    // 预览图片
    previewImg(e){
      const indexs = e.currentTarget.dataset.index
      let urlList = []
      this.data.picList.forEach((item)=>{
        urlList.push(item.tempFilePath)
      })
      wx.previewImage({
        current: this.data.picList[indexs].tempFilePath, // 当前显示图片的 http 链接
        urls: urlList // 需要预览的图片 http 链接列表
      })
    },
  }

CSS

.areaBlock{
    width: 100%;
    height: 100%;
}
.picList{
    padding: 0 30rpx 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    position: relative;
}
.areaMove{
    position: absolute;
    left: 0;
    top: 0;
    width: 196rpx;
    height: 196rpx;
}
.areaMove image{
    width: 100%;
    height: 100%;
    border-radius: 10rpx;
}
.areaImg{
    box-shadow: 0 2rpx 18rpx 0 #7BC4FF;
}
.picRelative{
    position: relative;
    width: 196rpx;
    height: 196rpx;
    margin-right: 40rpx;
    margin-bottom: 40rpx;
    border: 1rpx dashed rgba(0, 0, 0, 0.06);
}
.picRelative:nth-child(3n){
    margin-right: 0;
}
.dynamicImg{
    width: 100%;
    height: 100%;
    border-radius: 10rpx;
}
.deleteImg{
    position: absolute;
    top: -20rpx;
    right: -20rpx;
    z-index: 2;
    width: 44rpx;
    height: 44rpx;
}

三、总结

图片到达可交换位置的容错值及图片一行的数量可以因需求而异。

如果有逻辑错误或冗余代码敬请指正。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值