微信小程序图片上传,删除,拖拽,(裁剪参考链接,参看说明5.6)

场景:从相册中选择照片,展示图片列表,删除某张不需要的图片,通过拖拽调整图片的位置顺序。

1.wxml



  
    

      
        
        

        
        {{(item.upload_percent
          <100)?item.upload_percent:item.errormsg}}%
            封面
            
        

        
        
          
        

        
        
          添加图片
        
    
    
    
    
      小技巧:长按图片拖动可修改封面图片
      完成
    
  

2.wxss

.uploadPic {
  padding: 35rpx 20rpx 0;
  box-sizing: border-box;
}

.uploadPic-ul {
  box-sizing: border-box;
  width: 100%;
  padding-bottom: 244rpx;
}

.uploadPic-ul-wrap {
  width: 765rpx;
}

.uploadPic-li {
  width: 155rpx;
  height: 150rpx;
  position: relative;
  float: left;
  margin-right: 30rpx;
  margin-bottom: 30rpx;
}

.uploadPic-li .uploadPic-li-camer {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAjCAYAAADmOUiuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjQ5RDBDNzkzOThCNzExRTk4NjhBQTU0NDhGMjc1REE4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjQ5RDBDNzk0OThCNzExRTk4NjhBQTU0NDhGMjc1REE4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NDlEMEM3OTE5OEI3MTFFOTg2OEFBNTQ0OEYyNzVEQTgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NDlEMEM3OTI5OEI3MTFFOTg2OEFBNTQ0OEYyNzVEQTgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4iYtH1AAAC2ElEQVR42syYW4hNURjH1z7GDEWSQYZxbyiTpJMMNeTy4IEUJ+bBG8WQZnJ7oSnmCQ8SUcotwjkuqSFmPEwemMaD0FCjITUPhppcShpm+H/1P1rt9j5n1tp7mfOvX2ufs9dZ63/2Xuv7vr29dDqtLJQAR8A6MAH0gz++Ph77fQdPQSPo9A+USqVyTlRkYa4cNIO5g+w/EcwGm0ENuGV6JUx1w8CcruHgps2tMtEcUKWi6bBLg1dUdB0y6exfg5PAUjDSt+hlE0wGSRWPzoJWmT+Tyeibqg+8x8Zp//eltovl0u8HJWro9QDshNF3WYN3wHpVWJLwNFPWYHUBmhONBhfFYF1Ihx7wcYhNrpBNMj3gxGOwmhtFAuvaPAPJH3kB3oJfDObJkLGV6S7u930nplZxItEW8CXk9y3gIGgPOS8GD4Dtlv5+i8GBgBxaATr4eUbIj2XiozweAzaAqYytveAheAN2gCZwnnnb+AoGSXLtVpo9EXB+I299sRaevIB+EuQawD2wCDwD4+MwWAbuh5yrp7mx4DmYlmP8FJH1/AgsA69dprouXlFJ/E/ymPOv1SRv+XGXBmvZNlhUNOfY7gM/XBj8xLWpLHflArCYx20uDHaxXQnGWYaN3WxbXRjsYbskQtytYNvhwmAf21ERDCZ8Y8VqsJRtZwSDvWynuDBYrgVfW11jW+3C4CxmgW8MuqaS0HLZpUHpe4bHeywM7mUBsoaPD04CtRQE88BLHg9Wp7U/l7bZVSZqZh6+zUr8Q46+A8wcu/j5umkUsHmzUMaCVt4U3CViYiHLLalwuhnrTmlV+SWwKa5yK58qwSsWs1fBsRx9JbBf0IK0scFiS5MeH+QbWa20sFr5ySJ3OV8uVUYIS8OKOGAUSVm/jcStREILnoWobjF4EnwtUIP12TBTZVqK/wfJq4+m7C6WxT2fT2CS0kYEPO25lsc5P8urGJiTZKD+CjAABiiPPK6k5x4AAAAASUVORK5CYII=);
  background-repeat: no-repeat;
  background-position: center 37rpx;
  background-size: 40rpx 35rpx;
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: #f2f2f2;
  top: 0;
  left: 0;
  box-sizing: border-box;
  padding-top: 86rpx;
  text-align: center;
  font-size: 24rpx;
  color: #aaa;
  line-height: 28rpx;
}

.uploadPic-li-pic {
  width: 155rpx;
  height: 150rpx;
  position: absolute;
  left: 0;
  top: 0;
}

movable-view, movable-view .item-move, movable-view .item-move image {
  width: 155rpx;
  height: 150rpx;
}

.uploadPic-li-fm {
  width: 100%;
  height: 35rpx;
  line-height: 35rpx;
  text-align: center;
  background-color: #ff7500;
  font-size: 24rpx;
  color: #fff;
  position: absolute;
  left: 0;
  bottom: 0;
}

.uploadPic-li-close {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAYAAADgKtSgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkM0MDlCQ0MzOThCODExRTlCRTdCODYyQzA0QjY4MEJFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkM0MDlCQ0M0OThCODExRTlCRTdCODYyQzA0QjY4MEJFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QzQwOUJDQzE5OEI4MTFFOUJFN0I4NjJDMDRCNjgwQkUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QzQwOUJDQzI5OEI4MTFFOUJFN0I4NjJDMDRCNjgwQkUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7vcILQAAAA9klEQVR42rSVSw6CMBBACzGsvY6uYSUu9HCi4hWMS7yB7nAh3RpPoD1BnUlmCCE0gHSaPGhpeW36mSqrlHIQAjGwA0rgA1h6l/Q9pnadDpc4BSqS9VFR+155BOwHStsc6P9OOVYUf4qZotlBU36cKGbytnzlScykLMfVfnqWa/Qq2k5WgCSEwW+VTNqgfCkkXwR44iAzF5AblNu6aO10ZRDUWZyWr9C0mBk83vW0NHr1kF448pvQyO8oPwvJL3xCtdQJ5fjtU75uR8Xck/gkFc+vrnjOHeQTRhwNvUP1iMVLx1zQvIsSIAMegCGZoXJG9c7b/yfAALbzUJhUQ+vrAAAAAElFTkSuQmCC);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 23rpx 23rpx;
  width: 23rpx;
  height: 23rpx;
  padding: 10rpx;
  position: absolute;
  right: -22rpx;
  top: -22rpx;
}

.uploadPicB {
  width: 678rpx;
  position: fixed;
  bottom: 0;
  left: 50%;
  margin-left: -339rpx;
  padding-bottom: 90rpx;
}

.uploadPicB-msg {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAbCAYAAACTHcTmAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjc5ODFERjJCOThCQzExRTlCNUFFOTUxQTkzNDQ5RDYyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjc5ODFERjJDOThCQzExRTlCNUFFOTUxQTkzNDQ5RDYyIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6Nzk4MURGMjk5OEJDMTFFOUI1QUU5NTFBOTM0NDlENjIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6Nzk4MURGMkE5OEJDMTFFOUI1QUU5NTFBOTM0NDlENjIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7B1bc1AAACCUlEQVR42qSVSygFURjHZ9wrJEqU93tBIeWRUgixYYGysPMo5NHdcDc2FqSuDQvK5nplYYssJIkoZCdRqBulEKK8boz/xzd1umaYMV/9zumeM/O75zuvkZVeSS9yQTMoAllC+wnYAlNgXXIpP16UNaQpYBjUCW1n4AYEgwyhfRP0QLwrCvx8hDXglIVroBpEglRQADJBKCgH85zFjuSUO/VGWsoiiiZO76+oBAsgALRgxG5RSv9+C2ygmNMyGvGcnT9Ih/hYTX+chR0mhRIk5yhL+NecOtII1NfgEsRIZkNdfae8grIC5NFIG7h7SLIW/ep6+PGqSsIi/Tf2uM4naTT/eLCkdClelPcgkaSv3GyTrAftgDeSerghypLOKYfwiTsi6bKw4a1ELderJF3kKWi1KB3k2q1ufgfXS/9MvQ9lHBjDgt2o0gmwDapoHU0KG1EOADpZ3b63VBnflXQbOA0q6Z1J8AwKMUpF6z4NBHdcywak+yAHJEHo0btPX8CVieTTeON7xEa7xoMHIAGMCEfPNxS+vGlfXvh2aknbWOYwMFKS1xuRXvDng+YqHHxoPEPT9viVlUu5MiKleALJIFanX+YLaEOrU0+aDWYMpE/vjxqVHoIuEMYjsvH8yTwddt5202ZG6v06ct9Hj45gEHjnuaS+2d++ZfY/0qNj167Rns5fXc34FGAAZQl6B31aWcAAAAAASUVORK5CYII=);
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 21rpx 27rpx;
  padding-left: 33rpx;
  color: #666;
  font-size: 28rpx;
  line-height: 32rpx;
}

.uploadPicB-btn {
  width: 100%;
  height: 90rpx;
  line-height: 90rpx;
  text-align: center;
  color: #fff;
  font-size: 30rpx;
  border-radius: 10rpx;
  margin-top: 35rpx;
  background-color: #ff7500;
}

.uploadPic-li-msg {
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: #f2f2f2;
  top: 0;
  left: 0;
  box-sizing: border-box;
  padding-top: 55rpx;
  text-align: center;
  font-size: 24rpx;
  color: #aaa;
  line-height: 28rpx;
  word-break: break-all;
  word-wrap: break-word;
  z-index: 1;
}

movable-area {
  width: 100%;
  height: 100%;
}

3.js

var app = getApp();
// 这里是请求方法的封装
// var common = require('../../util/util.js');
var that;
Page({

  /**
   * 页面的初始数据
   */
  data: {
    tempFilePaths: [],
    // 最大照片数量的限制
    imgnum: 6,
    disabled: true,
    elements: [],
    hidden: true,
    flag: false,
    x: 0,
    y: 0,
    uploadPicKind: ''
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    that = this;
  },

  // 照片张数计算(和计算每张图片的位置,如果需要计算位置nodes=false,否则为true)
  getNumPic() {
    var num = that.data.tempFilePaths.length;

    var title = '上传照片(' + num + ')张';
    wx.setNavigationBarTitle({
      title: title
    });

  },

  // 获取图片的信息(位置信息)
  getElements(){

    var query = wx.createSelectorQuery();
    var nodesRef = query.selectAll(".uploadPic-li-pic");
    nodesRef.fields({
      dataset: true,
      rect: true
    }, (result) => {
      for (var i = 0; i < result.length; i++) {
        result[i].dataset['index'] = i
      }
      that.setData({
        elements: result
      });
    }).exec();
  },

  /*****
   * 上传图片
   ********/
  uploadpic: function(e) {
    var tempFilePaths = that.data.tempFilePaths;
    let num = that.data.imgnum - that.data.tempFilePaths.length;
    wx.chooseImage({
      count: num, // 默认9
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function(res) {
        // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
        var path = res.tempFiles;
        for (var i in res.tempFiles) {
          /**** 这里如果换为了服务器的,这里的 upload_percent 就得写为0,土武器上传完毕会改为对应的进度****/
          path[i]['upload_percent'] = 100;
          path[i]['src'] = '';
          path[i]['iserror'] = 0;
          path[i]['errormsg'] = '';
          tempFilePaths.push(path[i]);
        }
        that.setData({
          tempFilePaths: tempFilePaths
        }, () => {
          // 等赋值完毕后,再统计照片张数
          that.getNumPic();
          // 图片位置信息
          that.getElements();

        });

        // 上传服务器 (图片不能一次上传多张,需要一张一张上传,用了一个循环)
        for (var j in tempFilePaths) {
          if (tempFilePaths[j]['upload_percent'] == 0) {
            // that.upload_file_server(j)
          }
        }
      }
    })
  },
  // 上传服务器
  upload_file_server: function(j) {
    var keyinfo = that.data.tempFilePaths[j];

    var key = "tempFilePaths[" + j + "]";
    var upload_task = wx.uploadFile({
      // 这里是图片上传的图片服务器地址
      url: common.config.Sever_uploadImg,
      filePath: keyinfo['path'],
      name: 'file',
      success: function(res) {
        var returndata;
        if (typeof res.data == 'string') {
          returndata = JSON.parse(res.data)
        }
        if (res.statusCode != 200) {
          keyinfo['iserror'] = 1;
          keyinfo['errormsg'] = '网络错误';
        } else {
          if (returndata.code) {
            keyinfo['src'] = returndata.data;
            keyinfo['iserror'] = 0;
            keyinfo['errormsg'] = '成功';
          } else {
            keyinfo['iserror'] = 1;
            keyinfo['errormsg'] = returndata.msg;
          }
        }

        // 只是改变其中的某项
        that.setData({
          [key]: keyinfo,
        });
      }
    });
    upload_task.onProgressUpdate((res) => {
      keyinfo['upload_percent'] = res.progress
      that.setData({
        [key]: keyinfo,
      });
    })
  },

  /*****
   * 删除图片
   ********/
  delimg: function(e) {
    var datalist = that.data.tempFilePaths;
    var thiskey = e.currentTarget.dataset.keyindex;
    datalist.splice(thiskey, 1);
    that.setData({
      tempFilePaths: datalist
    }, () => {
      // 照片张数统计
      that.getNumPic();
    });

  },
  // 完成按钮
  uploadPicFinshed() {

    // 点击完成后的动作
    var tempFilePaths = that.data.tempFilePaths;

  },

  // 拖拽逻辑
  //长按
  _longtap: function(e) {
    var maskImg = e.currentTarget.dataset.img
    this.setData({
      maskImg: maskImg
    });

    this.setData({
      x: e.currentTarget.offsetLeft,
      y: e.currentTarget.offsetTop
    })
    this.setData({
      hidden: false,
      flag: true
    })
  },
  //触摸开始
  touchs: function(e) {
    this.setData({
      beginIndex: e.currentTarget.dataset.index
    })
  },
  //触摸结束
  touchend: function(e) {
    if (!this.data.flag) {
      return;
    }
    const x = e.changedTouches[0].pageX
    const y = e.changedTouches[0].pageY
    const list = this.data.elements;
    let data = this.data.tempFilePaths
    for (var j = 0; j < list.length; j++) {
      const item = list[j];
      if (x > item.left && x < item.right && y > item.top && y < item.bottom) {
        const endIndex = item.dataset.index;
        const beginIndex = this.data.beginIndex;
        //向后移动
        if (beginIndex < endIndex) {
          let tem = data[beginIndex];
          for (let i = beginIndex; i < endIndex; i++) {
            data[i] = data[i + 1]
          }
          data[endIndex] = tem;
        }
        //向前移动
        if (beginIndex > endIndex) {
          let tem = data[beginIndex];
          for (let i = beginIndex; i > endIndex; i--) {
            data[i] = data[i - 1]
          }
          data[endIndex] = tem;
        }

        this.setData({
          tempFilePaths: data
        });
      }
    }
    this.setData({
      hidden: true,
      flag: false
    })
  },
  //滑动
  touchm: function(e) {

    if (this.data.flag) {
      const x = e.touches[0].pageX
      const y = e.touches[0].pageY

      this.setData({
        x: x - 77,
        y: y - 75
      })
    }

  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function() {

  }
})

4.效果

微信小程序图片上传,删除,拖拽,(裁剪参考链接,参看说明5.6)_第1张图片  微信小程序图片上传,删除,拖拽,(裁剪参考链接,参看说明5.6)_第2张图片  微信小程序图片上传,删除,拖拽,(裁剪参考链接,参看说明5.6)_第3张图片

5.说明

5.1拖拽参照:

https://blog.csdn.net/haicome/article/details/82664344

https://blog.csdn.net/qq_35736512/article/details/89153197

5.2 小程序中的拖拽比较简单,小程序官方提供了组件

点击这里查看https://developers.weixin.qq.com/miniprogram/dev/component/movable-area.html

5.3 从相册选择照片或者相机拍照 wx.chooseImage

点击查看https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html

5.4 wx.uploadFile 官方地址

点击查看 https://developers.weixin.qq.com/miniprogram/dev/api/network/upload/wx.uploadFile.html

5.5 wx.createSelectorQuery 官方地址

点击查看 https://developers.weixin.qq.com/miniprogram/dev/api/wxml/wx.createSelectorQuery.html

5.6 图片裁剪

点击查看https://github.com/wx-plugin/image-cropper

 

你可能感兴趣的:(微信小程序)