gaoluyang
3 天以前 92230c9a97dc9ce9df3313d11d26999c04bb6b26
src/pages_mine/pages/avatar/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,642 @@
<template>
   <view class="container">
      <view class="page-body uni-content-info">
         <view class='cropper-content'>
            <view v-if="isShowImg" class="uni-corpper"
               :style="'width:' + cropperInitW + 'px;height:' + cropperInitH + 'px;background:#000'">
               <view class="uni-corpper-content"
                  :style="'width:' + cropperW + 'px;height:' + cropperH + 'px;left:' + cropperL + 'px;top:' + cropperT + 'px'">
                  <image :src="imageSrc" :style="'width:' + cropperW + 'px;height:' + cropperH + 'px'"></image>
                  <view class="uni-corpper-crop-box" @touchstart.stop="contentStartMove"
                     @touchmove.stop="contentMoveing" @touchend.stop="contentTouchEnd"
                     :style="'left:' + cutL + 'px;top:' + cutT + 'px;right:' + cutR + 'px;bottom:' + cutB + 'px'">
                     <view class="uni-cropper-view-box">
                        <view class="uni-cropper-dashed-h"></view>
                        <view class="uni-cropper-dashed-v"></view>
                        <view class="uni-cropper-line-t" data-drag="top" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-line-r" data-drag="right" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-line-b" data-drag="bottom" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-line-l" data-drag="left" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-point point-t" data-drag="top" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-point point-tr" data-drag="topTight"></view>
                        <view class="uni-cropper-point point-r" data-drag="right" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-point point-rb" data-drag="rightBottom"
                           @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-point point-b" data-drag="bottom" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove" @touchend.stop="dragEnd"></view>
                        <view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view>
                        <view class="uni-cropper-point point-l" data-drag="left" @touchstart.stop="dragStart"
                           @touchmove.stop="dragMove"></view>
                        <view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
                     </view>
                  </view>
               </view>
            </view>
         </view>
         <view class='cropper-config'>
            <button type="primary reverse" @click="getImage" style='margin-top: 30rpx;'> é€‰æ‹©å¤´åƒ </button>
            <button type="warn" @click="getImageInfo" style='margin-top: 30rpx;'> æäº¤ </button>
         </view>
         <canvas canvas-id="myCanvas"
            :style="'position:absolute;border: 1px solid red; width:' + imageW + 'px;height:' + imageH + 'px;top:-9999px;left:-9999px;'"></canvas>
      </view>
   </view>
</template>
<script>
import config from '@/config'
import { uploadAvatar } from "@/api/system/user"
import useUserStore from '@/store/modules/user'
const baseUrl = config.baseUrl
let sysInfo = uni.getSystemInfoSync()
let SCREEN_WIDTH = sysInfo.screenWidth
let PAGE_X, // æ‰‹æŒ‰ä¸‹çš„x位置
   PAGE_Y, // æ‰‹æŒ‰ä¸‹y的位置
   PR = sysInfo.pixelRatio, // dpi
   T_PAGE_X, // æ‰‹ç§»åŠ¨çš„æ—¶å€™x的位置
   T_PAGE_Y, // æ‰‹ç§»åŠ¨çš„æ—¶å€™Y的位置
   CUT_L, // åˆå§‹åŒ–拖拽元素的left值
   CUT_T, // åˆå§‹åŒ–拖拽元素的top值
   CUT_R, // åˆå§‹åŒ–拖拽元素的
   CUT_B, // åˆå§‹åŒ–拖拽元素的
   CUT_W, // åˆå§‹åŒ–拖拽元素的宽度
   CUT_H, //  åˆå§‹åŒ–拖拽元素的高度
   IMG_RATIO, // å›¾ç‰‡æ¯”例
   IMG_REAL_W, // å›¾ç‰‡å®žé™…的宽度
   IMG_REAL_H, // å›¾ç‰‡å®žé™…的高度
   DRAFG_MOVE_RATIO = 1, //移动时候的比例,
   INIT_DRAG_POSITION = 100, // åˆå§‹åŒ–屏幕宽度和裁剪区域的宽度之差,用于设置初始化裁剪的宽度
   DRAW_IMAGE_W = sysInfo.screenWidth // è®¾ç½®ç”Ÿæˆçš„图片宽度
export default {
   /**
    * é¡µé¢çš„初始数据
    */
   data() {
      return {
         imageSrc: useUserStore().avatar,
         isShowImg: false,
         // åˆå§‹åŒ–的宽高
         cropperInitW: SCREEN_WIDTH,
         cropperInitH: SCREEN_WIDTH,
         // åŠ¨æ€çš„å®½é«˜
         cropperW: SCREEN_WIDTH,
         cropperH: SCREEN_WIDTH,
         // åŠ¨æ€çš„left top值
         cropperL: 0,
         cropperT: 0,
         transL: 0,
         transT: 0,
         // å›¾ç‰‡ç¼©æ”¾å€¼
         scaleP: 0,
         imageW: 0,
         imageH: 0,
         // è£å‰ªæ¡† å®½é«˜
         cutL: 0,
         cutT: 0,
         cutB: SCREEN_WIDTH,
         cutR: '100%',
         qualityWidth: DRAW_IMAGE_W,
         innerAspectRadio: DRAFG_MOVE_RATIO
      }
   },
   /**
    * ç”Ÿå‘½å‘¨æœŸå‡½æ•°--监听页面初次渲染完成
    */
   onReady: function () {
      this.loadImage()
   },
   methods: {
      setData: function (obj) {
         let that = this
         Object.keys(obj).forEach(function (key) {
            that.$set(that.$data, key, obj[key])
         })
      },
      getImage: function () {
         var _this = this
         uni.chooseImage({
            success: function (res) {
               _this.setData({
                  imageSrc: res.tempFilePaths[0],
               })
               _this.loadImage()
            },
         })
      },
      loadImage: function () {
         var _this = this
         uni.getImageInfo({
            src: _this.imageSrc,
            success: function success(res) {
               IMG_RATIO = 1 / 1
               if (IMG_RATIO >= 1) {
                  IMG_REAL_W = SCREEN_WIDTH
                  IMG_REAL_H = SCREEN_WIDTH / IMG_RATIO
               } else {
                  IMG_REAL_W = SCREEN_WIDTH * IMG_RATIO
                  IMG_REAL_H = SCREEN_WIDTH
               }
               let minRange = IMG_REAL_W > IMG_REAL_H ? IMG_REAL_W : IMG_REAL_H
               INIT_DRAG_POSITION = minRange > INIT_DRAG_POSITION ? INIT_DRAG_POSITION : minRange
               // æ ¹æ®å›¾ç‰‡çš„宽高显示不同的效果   ä¿è¯å›¾ç‰‡å¯ä»¥æ­£å¸¸æ˜¾ç¤º
               if (IMG_RATIO >= 1) {
                  let cutT = Math.ceil((SCREEN_WIDTH / IMG_RATIO - (SCREEN_WIDTH / IMG_RATIO - INIT_DRAG_POSITION)) / 2)
                  let cutB = cutT
                  let cutL = Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH + INIT_DRAG_POSITION) / 2)
                  let cutR = cutL
                  _this.setData({
                     cropperW: SCREEN_WIDTH,
                     cropperH: SCREEN_WIDTH / IMG_RATIO,
                     // åˆå§‹åŒ–left right
                     cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
                     cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH / IMG_RATIO) / 2),
                     cutL: cutL,
                     cutT: cutT,
                     cutR: cutR,
                     cutB: cutB,
                     // å›¾ç‰‡ç¼©æ”¾å€¼
                     imageW: IMG_REAL_W,
                     imageH: IMG_REAL_H,
                     scaleP: IMG_REAL_W / SCREEN_WIDTH,
                     qualityWidth: DRAW_IMAGE_W,
                     innerAspectRadio: IMG_RATIO
                  })
               } else {
                  let cutL = Math.ceil((SCREEN_WIDTH * IMG_RATIO - (SCREEN_WIDTH * IMG_RATIO)) / 2)
                  let cutR = cutL
                  let cutT = Math.ceil((SCREEN_WIDTH - INIT_DRAG_POSITION) / 2)
                  let cutB = cutT
                  _this.setData({
                     cropperW: SCREEN_WIDTH * IMG_RATIO,
                     cropperH: SCREEN_WIDTH,
                     // åˆå§‹åŒ–left right
                     cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH * IMG_RATIO) / 2),
                     cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
                     cutL: cutL,
                     cutT: cutT,
                     cutR: cutR,
                     cutB: cutB,
                     // å›¾ç‰‡ç¼©æ”¾å€¼
                     imageW: IMG_REAL_W,
                     imageH: IMG_REAL_H,
                     scaleP: IMG_REAL_W / SCREEN_WIDTH,
                     qualityWidth: DRAW_IMAGE_W,
                     innerAspectRadio: IMG_RATIO
                  })
               }
               _this.setData({
                  isShowImg: true
               })
               uni.hideLoading()
            }
         })
      },
      // æ‹–动时候触发的touchStart事件
      contentStartMove(e) {
         PAGE_X = e.touches[0].pageX
         PAGE_Y = e.touches[0].pageY
      },
      // æ‹–动时候触发的touchMove事件
      contentMoveing(e) {
         var _this = this
         var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
         var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
         // å·¦ç§»
         if (dragLengthX > 0) {
            if (this.cutL - dragLengthX < 0) dragLengthX = this.cutL
         } else {
            if (this.cutR + dragLengthX < 0) dragLengthX = -this.cutR
         }
         if (dragLengthY > 0) {
            if (this.cutT - dragLengthY < 0) dragLengthY = this.cutT
         } else {
            if (this.cutB + dragLengthY < 0) dragLengthY = -this.cutB
         }
         this.setData({
            cutL: this.cutL - dragLengthX,
            cutT: this.cutT - dragLengthY,
            cutR: this.cutR + dragLengthX,
            cutB: this.cutB + dragLengthY
         })
         PAGE_X = e.touches[0].pageX
         PAGE_Y = e.touches[0].pageY
      },
      contentTouchEnd() {
      },
      // èŽ·å–å›¾ç‰‡
      getImageInfo() {
         var _this = this
         uni.showLoading({
            title: '图片生成中...',
         })
         // å°†å›¾ç‰‡å†™å…¥ç”»å¸ƒ
         const ctx = uni.createCanvasContext('myCanvas')
         ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H)
         ctx.draw(true, () => {
            // èŽ·å–ç”»å¸ƒè¦è£å‰ªçš„ä½ç½®å’Œå®½åº¦   å‡ä¸ºç™¾åˆ†æ¯” * ç”»å¸ƒä¸­å›¾ç‰‡çš„宽度    ä¿è¯äº†åœ¨å¾®ä¿¡å°ç¨‹åºä¸­è£å‰ªçš„图片模糊  ä½ç½®ä¸å¯¹çš„问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
            var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W
            var canvasH = ((_this.cropperH - _this.cutT - _this.cutB) / _this.cropperH) * IMG_REAL_H
            var canvasL = (_this.cutL / _this.cropperW) * IMG_REAL_W
            var canvasT = (_this.cutT / _this.cropperH) * IMG_REAL_H
            uni.canvasToTempFilePath({
               x: canvasL,
               y: canvasT,
               width: canvasW,
               height: canvasH,
               destWidth: canvasW,
               destHeight: canvasH,
               quality: 0.5,
               canvasId: 'myCanvas',
               success: function (res) {
                  uni.hideLoading()
                  let data = { name: 'avatarfile', filePath: res.tempFilePath }
                  uploadAvatar(data).then(response => {
                     // userStore.avatar =  response.imgUrl
                     /*cloud*/
                     useUserStore().avatar = baseUrl + response.imgUrl
                     uni.showToast({ title: "修改成功", icon: 'success' })
                     uni.$emit('refresh');
                     uni.navigateBack();
                  })
               }
            })
         })
      },
      // è®¾ç½®å¤§å°çš„æ—¶å€™è§¦å‘çš„touchStart事件
      dragStart(e) {
         T_PAGE_X = e.touches[0].pageX
         T_PAGE_Y = e.touches[0].pageY
         CUT_L = this.cutL
         CUT_R = this.cutR
         CUT_B = this.cutB
         CUT_T = this.cutT
      },
      // è®¾ç½®å¤§å°çš„æ—¶å€™è§¦å‘çš„touchMove事件
      dragMove(e) {
         var _this = this
         var dragType = e.target.dataset.drag
         switch (dragType) {
            case 'right':
               var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
               if (CUT_R + dragLength < 0) dragLength = -CUT_R
               this.setData({
                  cutR: CUT_R + dragLength
               })
               break
            case 'left':
               var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
               if (CUT_L - dragLength < 0) dragLength = CUT_L
               if ((CUT_L - dragLength) > (this.cropperW - this.cutR)) dragLength = CUT_L - (this.cropperW - this.cutR)
               this.setData({
                  cutL: CUT_L - dragLength
               })
               break
            case 'top':
               var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
               if (CUT_T - dragLength < 0) dragLength = CUT_T
               if ((CUT_T - dragLength) > (this.cropperH - this.cutB)) dragLength = CUT_T - (this.cropperH - this.cutB)
               this.setData({
                  cutT: CUT_T - dragLength
               })
               break
            case 'bottom':
               var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
               if (CUT_B + dragLength < 0) dragLength = -CUT_B
               this.setData({
                  cutB: CUT_B + dragLength
               })
               break
            case 'rightBottom':
               var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
               var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
               if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B
               if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R
               let cutB = CUT_B + dragLengthY
               let cutR = CUT_R + dragLengthX
               this.setData({
                  cutB: cutB,
                  cutR: cutR
               })
               break
            default:
               break
         }
      }
   }
}
</script>
<style>
/* pages/uni-cropper/index.wxss */
.cropper-config {
   padding: 20rpx 40rpx;
}
.cropper-content {
   min-height: 750rpx;
   width: 100%;
}
.uni-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;
}
.uni-corpper-content {
   position: relative;
}
.uni-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;
}
/* ç§»åŠ¨å›¾ç‰‡æ•ˆæžœ */
.uni-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;
}
/* å†…部的信息 */
.uni-corpper-crop-box {
   position: absolute;
   background: rgba(255, 255, 255, 0.3);
   z-index: 2;
}
.uni-corpper-crop-box .uni-cropper-view-box {
   position: relative;
   display: block;
   width: 100%;
   height: 100%;
   overflow: visible;
   outline: 1rpx solid #69f;
   outline-color: rgba(102, 153, 255, .75)
}
/* æ¨ªå‘虚线 */
.uni-cropper-dashed-h {
   position: absolute;
   top: 33.33333333%;
   left: 0;
   width: 100%;
   height: 33.33333333%;
   border-top: 1rpx dashed rgba(255, 255, 255, 0.5);
   border-bottom: 1rpx dashed rgba(255, 255, 255, 0.5);
}
/* çºµå‘虚线 */
.uni-cropper-dashed-v {
   position: absolute;
   left: 33.33333333%;
   top: 0;
   width: 33.33333333%;
   height: 100%;
   border-left: 1rpx dashed rgba(255, 255, 255, 0.5);
   border-right: 1rpx dashed rgba(255, 255, 255, 0.5);
}
/* å››ä¸ªæ–¹å‘的线  ä¸ºäº†ä¹‹åŽçš„æ‹–动事件*/
.uni-cropper-line-t {
   position: absolute;
   display: block;
   width: 100%;
   background-color: #69f;
   top: 0;
   left: 0;
   height: 1rpx;
   opacity: 0.1;
   cursor: n-resize;
}
.uni-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;
}
.uni-cropper-line-r {
   position: absolute;
   display: block;
   background-color: #69f;
   top: 0;
   right: 0rpx;
   width: 1rpx;
   opacity: 0.1;
   height: 100%;
   cursor: e-resize;
}
.uni-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;
}
.uni-cropper-line-b {
   position: absolute;
   display: block;
   width: 100%;
   background-color: #69f;
   bottom: 0;
   left: 0;
   height: 1rpx;
   opacity: 0.1;
   cursor: s-resize;
}
.uni-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;
}
.uni-cropper-line-l {
   position: absolute;
   display: block;
   background-color: #69f;
   top: 0;
   left: 0;
   width: 1rpx;
   opacity: 0.1;
   height: 100%;
   cursor: w-resize;
}
.uni-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;
}
.uni-cropper-point {
   width: 5rpx;
   height: 5rpx;
   background-color: #69f;
   opacity: .75;
   position: absolute;
   z-index: 3;
}
.point-t {
   top: -3rpx;
   left: 50%;
   margin-left: -3rpx;
   cursor: n-resize;
}
.point-tr {
   top: -3rpx;
   left: 100%;
   margin-left: -3rpx;
   cursor: n-resize;
}
.point-r {
   top: 50%;
   left: 100%;
   margin-left: -3rpx;
   margin-top: -3rpx;
   cursor: n-resize;
}
.point-rb {
   left: 100%;
   top: 100%;
   -webkit-transform: translate3d(-50%, -50%, 0);
   transform: translate3d(-50%, -50%, 0);
   cursor: n-resize;
   width: 36rpx;
   height: 36rpx;
   background-color: #69f;
   position: absolute;
   z-index: 1112;
   opacity: 1;
}
.point-b {
   left: 50%;
   top: 100%;
   margin-left: -3rpx;
   margin-top: -3rpx;
   cursor: n-resize;
}
.point-bl {
   left: 0%;
   top: 100%;
   margin-left: -3rpx;
   margin-top: -3rpx;
   cursor: n-resize;
}
.point-l {
   left: 0%;
   top: 50%;
   margin-left: -3rpx;
   margin-top: -3rpx;
   cursor: n-resize;
}
.point-lt {
   left: 0%;
   top: 0%;
   margin-left: -3rpx;
   margin-top: -3rpx;
   cursor: n-resize;
}
/* è£å‰ªæ¡†é¢„览内容 */
.uni-cropper-viewer {
   position: relative;
   width: 100%;
   height: 100%;
   overflow: hidden;
}
.uni-cropper-viewer image {
   position: absolute;
   z-index: 2;
}
</style>