• (微信,支付宝)小程序头像上传选择裁剪区域


    <!--微信小程序 -->
    <view>
    <view bindtap='upEwm'>
      <view>头像</view>
      <image style='200rpx;height:200rpx;background-color:red' src='{{headImg}}'></image>
    </view>
    </view>
    
    <!--裁剪图片浮层-->
    <view class='fixed-upimg' wx:if="{{imageFixed}}">
      <view class="wx-content-info">
        <view wx:if="{{isShowImg}}" class="wx-corpper" style="{{cropperInitW}}rpx;height:{{cropperInitH}}rpx;background:#000">
          <view bindtap='upLoad' class="wx-corpper-content" style="{{cropperW}}rpx;height:{{cropperH}}rpx;left:{{cropperL}}rpx;top:{{cropperT}}rpx">
            <image src="{{imageSrc}}" style="{{cropperW}}rpx;height:{{cropperH}}rpx"></image>
            <view class="wx-corpper-crop-box" bindtouchstart="contentStartMove" bindtouchmove="contentMoveing" style="{{cutW}}rpx;height:{{cutH}}rpx;left:{{cutL}}rpx;top:{{cutT}}rpx">
              <view class="wx-cropper-view-box">
                <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>
        <canvas canvas-id="myCanvas" style="position:absolute;border: 1px solid red; {{imageW}}rpx;height:{{imageH}}rpx;top:-9999px;left:-9999px;"></canvas>
        <button type="primary" bindtap="getImageInfo" style="position:fixed;bottom:120rpx;90%;left:50%;transform:translate3d(-50%,0,0)"> 确认提交 </button>
      </view>
    </view>
    

      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: '', //头像上传
        imageFixed: false, //裁剪浮层
        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.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
            })
          }
        })
      },
    
      // 拖动时候触发的touchStart事件
      contentStartMove(e) {
        pageX = e.touches[0].pageX
        pageY = e.touches[0].pageY
      },
    
      // 拖动时候触发的touchMove事件
      contentMoveing(e) {
        var _this = this
        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(_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,
             canvasW,
            height: canvasH,
            destWidth: canvasW,
            destHeight: canvasH,
            canvasId: 'myCanvas',
            success: function(res) {
              wx.hideLoading()
              console.log('end:' + res.tempFilePath)
              _this.setData({
                imageFixed: false,
                headImg: 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() {
        var _this = this
        wx.chooseImage({
          count: 1, // 默认9
          sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
          sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
          success: function(res) {
            var tempFilePaths = res.tempFilePaths[0];
            console.log('shangchuan:' + tempFilePaths)
            _this.setData({
              imageFixed: true,
              imageSrc: tempFilePaths
            })
            // 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,
                    headImg: 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()
              }
            })
          }
        })
      },
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: 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;
         100%;
        min- 0 !important;
        max- 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;
         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;
         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;
         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;
         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;
         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;
       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;
         1px;
        opacity: 0.1;
        height: 100%;
        cursor: e-resize;
    }
    .wx-cropper-line-r::before{
      content: '';
      position: absolute;
      top: 0;
      left: 50%;
       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;
         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;
       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;
         1px;
        opacity: 0.1;
        height: 100%;
        cursor: w-resize;
    }
    .wx-cropper-line-l::before{
      content: '';
      position: absolute;
      top: 0;
      left: 50%;
       41rpx;
      -webkit-transform: translate3d(-50%,0,0);
      transform: translate3d(-50%,0,0);
      bottom: 0;
      height: 100%;
      background: transparent;
      z-index: 11;
    }
     
    .wx-cropper-point{
         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;
         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;
       100%;
      height: 100%;
      overflow: hidden;
    }
     
    .wx-cropper-viewer image{
      position: absolute;
      z-index: 2;
    }
    

      支付宝小程序

    <!--图片展示 -->
    <view>
    <view onTap='upEwm'>
      <view>头像</view>
      <image style='200rpx;height:200rpx;background-color:red' src='{{headImg}}'></image>
    </view>
    </view>
    
    <!--裁剪图片浮层-->
    <view class='fixed-upimg' a:if="{{imageFixed}}">
      <view class="wx-content-info">
        <view a:if="{{isShowImg}}" class="wx-corpper" style="{{cropperInitW}}rpx;height:{{cropperInitH}}rpx;background:#000">
          <view onTap='upLoad' class="wx-corpper-content" style="{{cropperW}}rpx;height:{{cropperH}}rpx;left:{{cropperL}}rpx;top:{{cropperT}}rpx">
            <image src="{{imageSrc}}" style="{{cropperW}}rpx;height:{{cropperH}}rpx"></image>
            <view class="wx-corpper-crop-box" onTouchStart="contentStartMove" onTouchMove="contentMoveing" style="{{cutW}}rpx;height:{{cutH}}rpx;left:{{cutL}}rpx;top:{{cutT}}rpx">
              <view class="wx-cropper-view-box">
                <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>
        <canvas id="myCanvas" style="position:absolute;border: 1px solid red; {{imageW}}rpx;height:{{imageH}}rpx;top:-9999px;left:-9999px;"></canvas>
        <button type="primary" onTap="getImageInfo" style="position:fixed;bottom:120rpx;90%;left:50%;transform:translate3d(-50%,0,0)"> 确认提交 </button>
    
      </view>
    </view>

    js

    var windowWRPX = 750
    // 拖动时候的 pageX
    var pageX = 0
    // 拖动时候的 pageY
    var pageY = 0
    
    var pixelRatio = my.getSystemInfoSync().pixelRatio
    console.log(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://topmdrt-static.oss-cn-shenzhen.aliyuncs.com/images/testimg2.jpeg',
        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,
      },
      onLoad: function () {
        var _this = this
        my.getImageInfo({
          src: _this.data.imageSrc,
          success: function success(res) {
            console.log(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
            })
            my.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)
        my.showLoading({
          title: '图片生成中...',
        })
    
        // 将图片写入画布             
        const ctx = my.createCanvasContext('myCanvas')
        console.log(1)
    
        my.getImageInfo({
          src:_this.data.imageSrc,
          success:(res)=>{
            console.log(res)
          }
        })
        console.log(11,_this.data.cropperW,_this.data.cropperH)
        ctx.drawImage(_this.data.imageSrc,0,0,_this.data.imageW/pixelRatio,_this.data.imageH/pixelRatio)
            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}`)
        console.log(2)
        ctx.draw(true, function () {
          console.log(3, true)
          ctx.toTempFilePath({
              x: canvasL,
               y: canvasT,
                canvasW,
               height: canvasH,
               destWidth: canvasW,
               destHeight: canvasH,
            success: function (res) {
              my.hideLoading()
              // 成功获得地址的地方
              console.log(4, res)
              console.log('end:' + res.apFilePath)
              // 判断时上传头像还是二维码
              _this.setData({
                imageFixed: false,
                headImg: res.apFilePath
              })
            }
          })
        })
    
        console.log(5)
        //   }
        /*
       
       
         
        , () => {
             // 获取画布要裁剪的位置和宽度   均为百分比 * 画布中图片的宽度    保证了在微信小程序中裁剪的图片模糊  位置不对的问题
           
            
            
           }
        */
    
        // })
      },
      // 设置大小的时候触发的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;
        }
      },
    
      upEwm: function () {
        var _this = this
        my.chooseImage({
          count: 1, // 默认9
          sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
          sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
          success: function (res) {
            console.log(res)
            // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
            var tempFilePaths = res.apFilePaths[0];
            // var mode = parseFloat(e.currentTarget.dataset.current);
            console.log('shangchuan:' + tempFilePaths)
    
            _this.setData({
              imageFixed: true,
              imageSrc: tempFilePaths
            })
            // start
            my.getImageInfo({
              src: _this.data.imageSrc,
              success: function success(res) {
                console.log('getImageInfo',res)
                var innerAspectRadio = res.width / res.height;
                console.log('bili' + innerAspectRadio)
                // 根据图片的宽高显示不同的效果   保证图片可以正常显示
    
    
                if (innerAspectRadio == '1') {
                  _this.setData({
                    imageFixed: false,
                     headImg: tempFilePaths.join()
                  })
                } else if (innerAspectRadio > 1) {
                  console.log(res.width ,pixelRatio)
                  _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
                })
                // my.hideLoading()
              }
            })
          }
        })
      },
    
    })
    
    
    /*Page({
      data: {
        src: '/imgs/timg.jpg',
        height: 375,
         375,
        windowWidth: '',
        kuang:{
          left:0,
          top:100
        }
      },
      onLoad(query) {
        // 页面加载
        my.setCanPullDown({
          canPullDown: false
        })
        //  my.getSystemInfo({
        //     success:function(res){
        //      windowWidth: res.windowWidth
        //     }
        //   })
        // 页面显示
    
        // console.info(my.getSystemInfoSync().windowHeight);
      },
    
      onReady() {
        // 页面加载完成
      },
      onMovableViewChange(e) {
        console.log(1, e)
      },
      onMovableViewChangeEnd(e) {
        console.log(2, e)
      },
      onShow() {
        let _this = this;
    
      },
      qq1() {
        let _t = this;
        var ctx = my.createCanvasContext('canvasid');
         ctx.setFillStyle('#fff');
        let path = _t.data.src;
        ctx.drawImage(path, 0, 0, _t.data.width, _t.data.height);//我们要在canvas中画一张和放大之后的图片宽高一样的图片
      // ctx.save();
        // ctx.setStrokeStyle('blue');
        // ctx.rect(0, 0, 200,200);
        // ctx.stroke();
        ctx.draw();
      },
      move(e){
        console.log(e.touches[0])
        var that = this;
        var canvasW = 200;
        var canvasH = 200;
        let touches =e.touches[0];
        var x = touches.x;
        var y = touches.y;
        that.setData({
          ['kuang.left']:x,
          ['kuang.top']:y
        })
      },
      //上传图片
      qq(e) {
        console.log(e)
        let _this = this;
    
        my.chooseImage({
          count: 1,
          sizeType: ['original'],
          success: function (res) {
            console.log(res)
            _this.setData({
              src: res.apFilePaths[0]
            })
            _this.aa(res.apFilePaths[0])
          }
        })
      },
      aa(q) {
        let _this = this;
    
        my.getImageInfo({
          src: q,
          success: (res) => {
            console.log(1, res)
            var str = res.width / res.height;
    
            console.log('width', str)
            if (str > 1) {
              console.log(11111)
              _this.setData({
                height: 200,
                 str * 200
              })
            } else if (str < 1) {//竖版图片
            console.log(22222)
              _this.setData({
                 200,
                height: str * 200
              })
            } else if (str == 1) {
                console.log(33333)
               _this.setData({
                 200,
                height:200
              })
            }
          }
        })
      },
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
      generate: function () {
        var _this = this;
        const ctx_A = my.createCanvasContext('myCanvas_A');
        var baseWidth = _this.data.baseWidth * _this.data.Scale;//图片放大之后的宽
        var baseHeight = _this.data.baseHeight * _this.data.Scale;//图片放大之后的高
        ctx_A.drawImage(_this.data.src, 0, 0, baseWidth, baseHeight);//我们要在canvas中画一张和放大之后的图片宽高一样的图片
        ctx_A.draw();
        my.showToast({
          title: '截取中...',
          icon: 'loading',
          duration: 10000
        });//
        setTimeout(function () {//给延时是因为canvas画图需要时间
          ctx_A.toTempFilePath({//调用方法,开始截取
            x: _this.data.x,
            y: _this.data.y,
             400,
            height: 400,
            destWidth: 400,
            destHeight: 400,
            canvasId: 'myCanvas_A',
            success: function (res) {
              console.log(res.tempFilePath);
            }
          })
        }, 2000)
    
      },
      onHide() {
        // 页面隐藏
      },
      onUnload() {
        // 页面被关闭
      },
      onTitleClick() {
        // 标题被点击
      },
      onPullDownRefresh() {
        // 页面被下拉
      },
      onReachBottom() {
        // 页面被拉到底部
      },
      onShareAppMessage() {
        // 返回自定义分享信息
        return {
          title: 'My App',
          desc: 'My App description',
          path: 'pages/index/index',
        };
      },
    });
    */
  • 相关阅读:
    What is Split Brain in Oracle Clusterware and Real Application Cluster (文档 ID 1425586.1)
    Oracle Grid Infrastructure: Understanding Split-Brain Node Eviction (文档 ID 1546004.1)
    代理模式和装饰者模式区别
    偏向锁、轻量级锁、重量级锁
    理解HTTP幂等性
    Java8 lambda表达式10个示例
    IDEA debug断点调试技巧
    【1】【leetcode-115 动态规划】 不同的子序列
    【leetcode-91 动态规划】 解码方法
    【leetcode-78 dfs+回溯】 子集
  • 原文地址:https://www.cnblogs.com/caoruichun/p/10505586.html
Copyright © 2020-2023  润新知