小程序实现图片裁剪上传

小程序实现图片裁剪上传

本文实例为大家分享了小程序实现图片裁剪上传的具体代码,供大家参考,具体内容如下

<!--图片展示 --> <view bindtap='upEwm' data-which='1'>   <view>第一个图</view>   <image style='width:200rpx;height:200rpx;background-color:red' src='{{headImg}}'></image> </view> <view bindtap='upEwm' data-which='2'>   <view>第二个图</view>   <image style='width:200rpx;height:200rpx;background-color:red' src='{{ewmImg}}'></image> </view> <!--裁剪图片浮层--> <view class='fixed-upimg' wx:if="{{imageFixed}}">   <view class="wx-content-info">     <!-- <view class="wx-content-info" wx:if="{{imageSrc}}"> -->     <view wx:if="{{isShowImg}}" class="wx-corpper" style="width:{{cropperInitW}}rpx;height:{{cropperInitH}}rpx;background:#000">       <view bindtap='upLoad' class="wx-corpper-content" style="width:{{cropperW}}rpx;height:{{cropperH}}rpx;left:{{cropperL}}rpx;top:{{cropperT}}rpx">         <image src="{{imageSrc}}" style="width:{{cropperW}}rpx;height:{{cropperH}}rpx"></image>         <view class="wx-corpper-crop-box" bindtouchstart="contentStartMove" bindtouchmove="contentMoveing" style="width:{{cutW}}rpx;height:{{cutH}}rpx;left:{{cutL}}rpx;top:{{cutT}}rpx">           <view class="wx-cropper-view-box">             <!-- <view class="wx-cropper-viewer">             <image src="{{imageSrc}}" style="width:{{cropperW}}rpx;height:{{cropperH}}rpx;left:{{cropperL - cutL}}rpx;top:{{cropperT - cutT}}rpx"></image>           </view> -->             <view class="wx-cropper-dashed-h"></view>             <view class="wx-cropper-dashed-v"></view>             <view class="wx-cropper-line-t" data-drag="top" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-line-r" data-drag="right" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-line-b" data-drag="bottom" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-line-l" data-drag="left" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-point point-t" data-drag="top" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-point point-tr" data-drag="topTight"></view>             <view class="wx-cropper-point point-r" data-drag="right" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-point point-rb" data-drag="rightBottom" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-point point-b" data-drag="bottom" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-point point-bl" data-drag="bottomLeft"></view>             <view class="wx-cropper-point point-l" data-drag="left" catchtouchstart="dragStart" catchtouchmove="dragMove"></view>             <view class="wx-cropper-point point-lt" data-drag="leftTop"></view>           </view>         </view>       </view>       <!-- <view class="wx-cropper-drag-box"></view> -->     </view>     <canvas canvas-id="myCanvas" style="position:absolute;border: 1px solid red; width:{{imageW}}rpx;height:{{imageH}}rpx;top:-9999px;left:-9999px;"></canvas>     <button type="primary" bindtap="getImageInfo" style="position:fixed;bottom:120rpx;width:90%;left:50%;transform:translate3d(-50%,0,0)"> 确认提交 </button>   </view> </view>

js:

// pages/wx-cropper/index.js // 手机的宽度 var windowWRPX = 750 // 拖动时候的 pageX var pageX = 0 // 拖动时候的 pageY var pageY = 0 var pixelRatio = wx.getSystemInfoSync().pixelRatio // 调整大小时候的 pageX var sizeConfPageX = 0 // 调整大小时候的 pageY var sizeConfPageY = 0 var initDragCutW = 0 var initDragCutL = 0 var initDragCutH = 0 var initDragCutT = 0 // 移动时 手势位移与 实际元素位移的比 var dragScaleP = 2 Page({   /**    * 页面的初始数据    */   data: {     imageNum: '', //上传的图片id     headImg: '', //头像上传     ewmImg: '', //二维码上传     imageFixed: false, //裁剪浮层     // imageSrc: 'http://huoche.7234.cn/images/jb51/dog1yhomvkm.webp',     imageSrc: '', //要裁剪的图片     returnImage: '',     isShowImg: false,     // 初始化的宽高     cropperInitW: windowWRPX,     cropperInitH: windowWRPX,     // 动态的宽高     cropperW: windowWRPX,     cropperH: windowWRPX,     // 动态的left top值     cropperL: 0,     cropperT: 0,     // 图片缩放值     scaleP: 0,     imageW: 0,     imageH: 0,     // 裁剪框 宽高     cutW: 400,     cutH: 400,     cutL: 0,     cutT: 0,   },   /**    * 生命周期函数--监听页面加载    */   onReady: function (options) {   },   /**    * 生命周期函数--监听页面初次渲染完成    */   onLoad: function () {     var _this = this     // wx.showLoading({     //   title: '图片加载中...',     // })     wx.getImageInfo({       src: _this.data.imageSrc,       success: function success(res) {         var innerAspectRadio = res.width / res.height;         console.log(innerAspectRadio)         // 根据图片的宽高显示不同的效果   保证图片可以正常显示         if (innerAspectRadio >= 1) {           _this.setData({             cropperW: windowWRPX,             cropperH: windowWRPX / innerAspectRadio,             // 初始化left right             cropperL: Math.ceil((windowWRPX - windowWRPX) / 2),             cropperT: Math.ceil((windowWRPX - windowWRPX / innerAspectRadio) / 2),             // 裁剪框  宽高              // cutW: windowWRPX - 200,             // cutH: windowWRPX / innerAspectRadio - 200,             cutL: Math.ceil((windowWRPX - windowWRPX + 340) / 2),             cutT: Math.ceil((windowWRPX / innerAspectRadio - (windowWRPX / innerAspectRadio - 20)) / 2),             // 图片缩放值             scaleP: res.width * pixelRatio / windowWRPX,             // 图片原始宽度 rpx             imageW: res.width * pixelRatio,             imageH: res.height * pixelRatio           })         } else {           _this.setData({             cropperW: windowWRPX * innerAspectRadio,             cropperH: windowWRPX,             // 初始化left right             cropperL: Math.ceil((windowWRPX - windowWRPX * innerAspectRadio) / 2),             cropperT: Math.ceil((windowWRPX - windowWRPX) / 2),             // 裁剪框的宽高             // cutW: windowWRPX * innerAspectRadio - 66,             // cutH: 400,             cutL: Math.ceil((windowWRPX * innerAspectRadio - (windowWRPX * innerAspectRadio - 20)) / 2),             cutT: Math.ceil((windowWRPX - 340) / 2),             // 图片缩放值             scaleP: res.width * pixelRatio / windowWRPX,             // 图片原始宽度 rpx             imageW: res.width * pixelRatio,             imageH: res.height * pixelRatio           })         }         _this.setData({           isShowImg: true         })         wx.hideLoading()       }     })   },   // 拖动时候触发的touchStart事件   contentStartMove(e) {     pageX = e.touches[0].pageX     pageY = e.touches[0].pageY   },   // 拖动时候触发的touchMove事件   contentMoveing(e) {     var _this = this     // _this.data.cutL + (e.touches[0].pageX - pageX)     // console.log(e.touches[0].pageX)     // console.log(e.touches[0].pageX - pageX)     var dragLengthX = (pageX - e.touches[0].pageX) * dragScaleP     var dragLengthY = (pageY - e.touches[0].pageY) * dragScaleP     var minX = Math.max(_this.data.cutL - (dragLengthX), 0)     var minY = Math.max(_this.data.cutT - (dragLengthY), 0)     var maxX = _this.data.cropperW - _this.data.cutW     var maxY = _this.data.cropperH - _this.data.cutH     this.setData({       cutL: Math.min(maxX, minX),       cutT: Math.min(maxY, minY),     })     console.log(`${maxX} ----- ${minX}`)     pageX = e.touches[0].pageX     pageY = e.touches[0].pageY   },   // 获取图片   getImageInfo() {     var _this = this     console.log('shengcheng:' + _this.data.imageSrc)     wx.showLoading({       title: '图片生成中...',     })     // wx.downloadFile({     //   url:_this.data.imageSrc, //仅为示例,并非真实的资源          //   success: function (res) {     // 将图片写入画布                  const ctx = wx.createCanvasContext('myCanvas')     // ctx.drawImage(res.tempFilePath)     ctx.drawImage(_this.data.imageSrc)     ctx.draw(true, () => {       // 获取画布要裁剪的位置和宽度   均为百分比 * 画布中图片的宽度    保证了在微信小程序中裁剪的图片模糊  位置不对的问题       var canvasW = (_this.data.cutW / _this.data.cropperW) * (_this.data.imageW / pixelRatio)       var canvasH = (_this.data.cutH / _this.data.cropperH) * (_this.data.imageH / pixelRatio)       var canvasL = (_this.data.cutL / _this.data.cropperW) * (_this.data.imageW / pixelRatio)       var canvasT = (_this.data.cutT / _this.data.cropperH) * (_this.data.imageH / pixelRatio)       console.log(`canvasW:${canvasW} --- canvasH: ${canvasH} --- canvasL: ${canvasL} --- canvasT: ${canvasT} -------- _this.data.imageW: ${_this.data.imageW}  ------- _this.data.imageH: ${_this.data.imageH} ---- pixelRatio ${pixelRatio}`)       wx.canvasToTempFilePath({         x: canvasL,         y: canvasT,         width: canvasW,         height: canvasH,         destWidth: canvasW,         destHeight: canvasH,         canvasId: 'myCanvas',         success: function (res) {           wx.hideLoading()           // 成功获得地址的地方           console.log('end:' + res.tempFilePath)           // 判断时上传头像还是二维码           _this.setData({             imageFixed: false,           })           if (_this.data.imageNum == '1') {             _this.setData({               headImg: res.tempFilePath             })           } else if (_this.data.imageNum == '2') {             _this.setData({               ewmImg: res.tempFilePath             })           }         }       })     })     //   }     // })   },   // 设置大小的时候触发的touchStart事件   dragStart(e) {     var _this = this     sizeConfPageX = e.touches[0].pageX     sizeConfPageY = e.touches[0].pageY     initDragCutW = _this.data.cutW     initDragCutL = _this.data.cutL     initDragCutT = _this.data.cutT     initDragCutH = _this.data.cutH   },   // 设置大小的时候触发的touchMove事件   dragMove(e) {     var _this = this     var dragType = e.target.dataset.drag     switch (dragType) {       case 'right':         var dragLength = (sizeConfPageX - e.touches[0].pageX) * dragScaleP         if (initDragCutW >= dragLength) {           // 如果 移动小于0 说明是在往下啦  放大裁剪的高度  这样一来 图片的高度  最大 等于 图片的top值加 当前图片的高度  否则就说明超出界限           if (dragLength < 0 && _this.data.cropperW > initDragCutL + _this.data.cutW) {             this.setData({               cutW: initDragCutW - dragLength             })           }           // 如果是移动 大于0  说明在缩小  只需要缩小的距离小于原本裁剪的高度就ok           if (dragLength > 0) {             this.setData({               cutW: initDragCutW - dragLength             })           }           else {             return           }         } else {           return         }         break;       case 'left':         var dragLength = (dragLength = sizeConfPageX - e.touches[0].pageX) * dragScaleP         console.log(dragLength)         if (initDragCutW >= dragLength && initDragCutL > dragLength) {           if (dragLength < 0 && Math.abs(dragLength) >= initDragCutW) return           this.setData({             cutL: initDragCutL - dragLength,             cutW: initDragCutW + dragLength           })         } else {           return;         }         break;       case 'top':         var dragLength = (sizeConfPageY - e.touches[0].pageY) * dragScaleP         if (initDragCutH >= dragLength && initDragCutT > dragLength) {           if (dragLength < 0 && Math.abs(dragLength) >= initDragCutH) return           this.setData({             cutT: initDragCutT - dragLength,             cutH: initDragCutH + dragLength           })         } else {           return;         }         break;       case 'bottom':         var dragLength = (sizeConfPageY - e.touches[0].pageY) * dragScaleP         // console.log(_this.data.cropperH > _this.data.cutT + _this.data.cutH)         console.log(dragLength)         console.log(initDragCutH >= dragLength)         console.log(_this.data.cropperH > initDragCutT + _this.data.cutH)         // 必须是 dragLength 向上缩小的时候必须小于原本的高度         if (initDragCutH >= dragLength) {           // 如果 移动小于0 说明是在往下啦  放大裁剪的高度  这样一来 图片的高度  最大 等于 图片的top值加 当前图片的高度  否则就说明超出界限           if (dragLength < 0 && _this.data.cropperH > initDragCutT + _this.data.cutH) {             this.setData({               cutH: initDragCutH - dragLength             })           }           // 如果是移动 大于0  说明在缩小  只需要缩小的距离小于原本裁剪的高度就ok           if (dragLength > 0) {             this.setData({               cutH: initDragCutH - dragLength             })           }           else {             return           }         } else {           return         }         break;       case 'rightBottom':         var dragLengthX = (sizeConfPageX - e.touches[0].pageX) * dragScaleP         var dragLengthY = (sizeConfPageY - e.touches[0].pageY) * dragScaleP         if (initDragCutH >= dragLengthY && initDragCutW >= dragLengthX) {           // bottom 方向的变化           if ((dragLengthY < 0 && _this.data.cropperH > initDragCutT + _this.data.cutH) || (dragLengthY > 0)) {             this.setData({               cutH: initDragCutH - dragLengthY             })           }           // right 方向的变化           if ((dragLengthX < 0 && _this.data.cropperW > initDragCutL + _this.data.cutW) || (dragLengthX > 0)) {             this.setData({               cutW: initDragCutW - dragLengthX             })           }           else {             return           }         } else {           return         }         break;       default:         break;     }   },   // 图片上传   upLoad: function () {   },   upEwm: function (e) {     var _this = this     wx.chooseImage({       count: 1, // 默认9       sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有       sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有       success: function (res) {         // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片         var tempFilePaths = res.tempFilePaths;         // var mode = parseFloat(e.currentTarget.dataset.current);         console.log('shangchuan:' + tempFilePaths)         console.log(e.currentTarget.dataset.which);         _this.setData({           imageFixed: true,           imageSrc: tempFilePaths.join(),           imageNum: e.currentTarget.dataset.which         })         // start         wx.getImageInfo({           src: _this.data.imageSrc,           success: function success(res) {             var innerAspectRadio = res.width / res.height;             console.log('bili' + innerAspectRadio)             // 根据图片的宽高显示不同的效果   保证图片可以正常显示             if (innerAspectRadio == '1') {               _this.setData({                 imageFixed: false,               })               // 判断时上传头像还是二维码               if (_this.data.imageNum == '1') {                 _this.setData({                   headImg: tempFilePaths.join()                 })               } else if (_this.data.imageNum == '2') {                 _this.setData({                   ewmImg: tempFilePaths.join()                 })               }             } else if (innerAspectRadio > 1) {               _this.setData({                 cropperW: windowWRPX,                 cropperH: windowWRPX / innerAspectRadio,                 // 初始化left right                 cropperL: Math.ceil((windowWRPX - windowWRPX) / 2),                 cropperT: Math.ceil((windowWRPX - windowWRPX / innerAspectRadio) / 2),                 // 裁剪框  宽高                  // cutW: windowWRPX - 200,                 // cutH: windowWRPX / innerAspectRadio - 200,                 cutL: Math.ceil((windowWRPX - windowWRPX + 340) / 2),                 cutT: Math.ceil((windowWRPX / innerAspectRadio - (windowWRPX / innerAspectRadio - 20)) / 2),                 // 图片缩放值                 scaleP: res.width * pixelRatio / windowWRPX,                 // 图片原始宽度 rpx                 imageW: res.width * pixelRatio,                 imageH: res.height * pixelRatio               })             } else {               _this.setData({                 cropperW: windowWRPX * innerAspectRadio,                 cropperH: windowWRPX,                 // 初始化left right                 cropperL: Math.ceil((windowWRPX - windowWRPX * innerAspectRadio) / 2),                 cropperT: Math.ceil((windowWRPX - windowWRPX) / 2),                 // 裁剪框的宽高                 // cutW: windowWRPX * innerAspectRadio - 66,                 // cutH: 400,                 cutL: Math.ceil((windowWRPX * innerAspectRadio - (windowWRPX * innerAspectRadio - 20)) / 2),                 cutT: Math.ceil((windowWRPX - 340) / 2),                 // 图片缩放值                 scaleP: res.width * pixelRatio / windowWRPX,                 // 图片原始宽度 rpx                 imageW: res.width * pixelRatio,                 imageH: res.height * pixelRatio               })             }             _this.setData({               isShowImg: true             })             wx.hideLoading()           }         })         // end       }     })   },   /**    * 生命周期函数--监听页面显示    */   onShow: function () {   },   /**    * 生命周期函数--监听页面隐藏    */   onHide: function () {   },   /**    * 生命周期函数--监听页面卸载    */   onUnload: function () {   },   /**    * 页面相关事件处理函数--监听用户下拉动作    */   onPullDownRefresh: function () {   },   /**    * 页面上拉触底事件的处理函数    */   onReachBottom: function () {   },   /**    * 用户点击右上角分享    */   onShareAppMessage: function () {   } })

css:

/* pages/wx-cropper/index.wxss */ .fixed-upimg{     position: fixed;   top: 0;   left: 0;   right: 0;   bottom: 0;   background-color: #fff; } .wx-content-info{   position: fixed;   top: 130rpx;   left: 0;   right: 0;   bottom: 0; } .wx-corpper{   position: relative;   overflow: hidden;   -webkit-user-select: none;   -moz-user-select: none;   -ms-user-select: none;   user-select: none;   -webkit-tap-highlight-color: transparent;   -webkit-touch-callout: none;   box-sizing: border-box; } .wx-corpper-content{     position: absolute;     top: 0;     right: 0;     bottom: 0;     left: 0; } .wx-corpper-content image {     display: block;     width: 100%;     min-width: 0 !important;     max-width: none !important;     height: 100%;     min-height: 0 !important;     max-height: none !important;     image-orientation: 0deg !important;     margin: 0 auto; } /* 移动图片效果 */ .wx-cropper-drag-box{     position: absolute;     top: 0;     right: 0;     bottom: 0;     left: 0;     cursor: move;     background: rgba(0,0,0,0.6);     z-index: 1; } /* 内部的信息 */ .wx-corpper-crop-box{     position: absolute;     width: 500rpx;     height: 500rpx;     background: rgba(255,255,255,0.3);     z-index: 2; } .wx-corpper-crop-box .wx-cropper-view-box {     position: relative;     display: block;     width: 100%;     height: 100%;     overflow: visible;     outline: 1px solid #69f;     outline-color: rgba(102, 153, 255, .75) } /* 横向虚线 */ .wx-cropper-dashed-h{     position: absolute;     top: 33.33333333%;     left: 0;     width: 100%;     height: 33.33333333%;     border-top: 1px dashed rgba(255,255,255,0.5);     border-bottom: 1px dashed rgba(255,255,255,0.5); } /* 纵向虚线 */ .wx-cropper-dashed-v{     position: absolute;     left: 33.33333333%;     top: 0;     width: 33.33333333%;     height: 100%;     border-left: 1px dashed rgba(255,255,255,0.5);     border-right: 1px dashed rgba(255,255,255,0.5); } /* 四个方向的线  为了之后的拖动事件*/ .wx-cropper-line-t{     position: absolute;     display: block;     width: 100%;     background-color: #69f;     top: 0;     left: 0;     height: 1px;     opacity: 0.1;     cursor: n-resize; } .wx-cropper-line-t::before{   content: '';   position: absolute;   top: 50%;   right: 0rpx;   width: 100%;   -webkit-transform: translate3d(0,-50%,0);   transform: translate3d(0,-50%,0);   bottom: 0;   height: 41rpx;   background: transparent;   z-index: 11; } .wx-cropper-line-r{     position: absolute;     display: block;     background-color: #69f;     top: 0;     right: 0px;     width: 1px;     opacity: 0.1;     height: 100%;     cursor: e-resize; } .wx-cropper-line-r::before{   content: '';   position: absolute;   top: 0;   left: 50%;   width: 41rpx;   -webkit-transform: translate3d(-50%,0,0);   transform: translate3d(-50%,0,0);   bottom: 0;   height: 100%;   background: transparent;   z-index: 11; } .wx-cropper-line-b{     position: absolute;     display: block;     width: 100%;     background-color: #69f;     bottom: 0;     left: 0;     height: 1px;     opacity: 0.1;     cursor: s-resize; } .wx-cropper-line-b::before{   content: '';   position: absolute;   top: 50%;   right: 0rpx;   width: 100%;   -webkit-transform: translate3d(0,-50%,0);   transform: translate3d(0,-50%,0);   bottom: 0;   height: 41rpx;   background: transparent;   z-index: 11; } .wx-cropper-line-l{     position: absolute;     display: block;     background-color: #69f;     top: 0;     left: 0;     width: 1px;     opacity: 0.1;     height: 100%;     cursor: w-resize; } .wx-cropper-line-l::before{   content: '';   position: absolute;   top: 0;   left: 50%;   width: 41rpx;   -webkit-transform: translate3d(-50%,0,0);   transform: translate3d(-50%,0,0);   bottom: 0;   height: 100%;   background: transparent;   z-index: 11; } .wx-cropper-point{     width: 5px;     height: 5px;     background-color: #69f;     opacity: .75;     position: absolute;     z-index: 3; } .point-t{     top: -3px;     left: 50%;     margin-left: -3px;     cursor: n-resize; } .point-tr{     top: -3px;     left: 100%;     margin-left: -3px;     cursor: n-resize; } .point-r{     top: 50%;     left:100%;     margin-left: -3px;     margin-top: -3px;     cursor: n-resize; } .point-rb{     left: 100%;     top: 100%;     -webkit-transform: translate3d(-50%,-50%,0);     transform: translate3d(-50%,-50%,0);     cursor: n-resize;     width: 24rpx;     height: 24rpx;     background-color: #69f;     position: absolute;     z-index: 1112;     opacity: 1; } .point-b{     left:50%;     top: 100%;     margin-left: -3px;     margin-top: -3px;     cursor: n-resize; } .point-bl{     left:0%;     top: 100%;     margin-left: -3px;     margin-top: -3px;     cursor: n-resize; } .point-l{     left:0%;     top: 50%;     margin-left: -3px;     margin-top: -3px;     cursor: n-resize; } .point-lt{     left:0%;     top: 0%;     margin-left: -3px;     margin-top: -3px;     cursor: n-resize; } /* 裁剪框预览内容 */ .wx-cropper-viewer{   position: relative;   width: 100%;   height: 100%;   overflow: hidden; } .wx-cropper-viewer image{   position: absolute;   z-index: 2; }

推荐阅读