Nuxt2+Vue2搭配vue-cropperjs实现头像裁剪并且上传

需求:因为上传图片过大,导致页面闪退,要求图片可裁剪(类似弹窗),然后再进行上传并且显示

事例图

注意:vue2和vue3所需要的vue-cropperjs版本不一致,安装时注意版本;

1、下载

npm install vue-cropperjs@4 cropperjs

2、安装

在plugins下创建vue-cropperjs.js文件

import Vue from 'vue'
import VueCropper from 'vue-cropperjs'
import 'cropperjs/dist/cropper.css'

Vue.component('vue-cropper', VueCropper)

并且nuxt2是服务端渲染,所以需要在nuxt.config.js中添加一些配置:

export default {
    ...
    plugins:[
        ...
        { src:'@/plugins/vue-cropperjs', ssr: false }
    ]
}

3、因为该需求只需在一个页面实现,所以博主就没有封装组件,直接在页面中使用

import VueCropper from 'vue-cropperjs'
import 'cropperjs/dist/cropper.css'

export default {
    components:{
        VueCropper
    }
}

相关html代码

        <div class="avatar-bg">
          <img v-if="userInfo.avatar" :src="getImageUrl(userInfo.avatar)">
          <input type="file" title="" accept="image/jpeg, image/png" class="img-input" @change="addHeadImg">
          <div class="img-font">
            上传
          </div>
        </div>
    <!-- 剪裁图片 -->
    <div v-if="cropperImage">
      <div class="cropper-shadow"></div>
      <div class="cropper-img">
        <img class="cropper-close" src="../../assets/img/close.png" @click="closeCropper">
        <div style="display: flex">
          <div style="width: 400px;height: 400px;margin-left: 40px;margin-top: 40px;">
            <VueCropper
              ref="cropper"
              :src="imgData"
              :view-mode="2"
              :aspect-ratio="1"
              :autoCropArea="0.5"
              :movable="false"
              :zoomable="false"
              :drag-mode="'move'"
              :img-style="{ 'width': '400px','height': '400px' }"
              @crop="onCrop"
            />
          </div>
          <div class="cropper-right">
            <img class="cropper-region" :src="croppedImageUrl" />
            <div style="width: 100%;text-align: center;margin-top: 10px">
              200px*200px
            </div>
          </div>
        </div>
        <div class="btn-box">
          <button class="btn-left" @click="closeCropper">
            取消
          </button>
          <button class="btn-right" @click="uploadImage">
            上传
          </button>
        </div>
      </div>
    </div>

注意: autoCropArea取值(0~1),可调节裁剪框的大小。并且vueCropper外层需包裹一层div,并且必须设置宽高

 相关js代码

export default {
    data(){
        ...
        cropperImage: false,
        imgData: null,
        cropperCanvas: null
    },
    computed:{
        croppedImageUrl () {
            if (this.cropperImage && this.cropperCanvas) {
                return this.cropperCanvas.toDataURL('image/jpeg')
              }
            return null
        }
    },
    methods:{
        /* 裁剪头像 */
        addHeadImg (event) {
            const file = event.target.files[0]
            if (file) {
                const reader = new FileReader()
                // 转化为base64
                reader.readAsDataURL(file)
                reader.onload = (e) => {
                  this.cropperImage = true
                  this.imgData = e.target.result
                }
            }
        },
        /* 裁剪框变化时的回调函数 */
        onCrop () {
          this.cropperCanvas = this.$refs.cropper.getCroppedCanvas()
        },
        /* 上传头像 */
        uploadImage () {
          const croppedCanvas = this.$refs.cropper.getCroppedCanvas()
          croppedCanvas.toBlob(async (blob) => {
            const formData = new FormData()
            formData.append('uploadFile', blob)
            const result = await this.$api.uploadApi(formData)
            if (result.status === 0) {
              this.$message({ message: '修改成功', type: 'success' })
              this.userInfo.avatar = result.data.filePath
            } else {
              this.$message({ showClose: true, message: '修改失败', type: 'error', duration: 3000 })
            }
            this.closeCropper()
          })
       }
    }
}

相关css代码

  .avatar-bg {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: #F6F6F6;
    border: 1px solid #F0F0F0;
    position: relative;
    img {
      height: 54px;
      width: 54px;
      border-radius: 50%;
    }
    &:hover {
      .img-font {
        display: block;
      }
    }
  }
  .img-input {
    z-index: 3;
    opacity: 0;
    cursor: pointer;
    left: 0;
    top: 0;
    position: absolute;
    height: 54px;
    width: 54px;
    border-radius: 50%;
  }
  .img-font {
    display: none;
    background: rgba(0,0,0,.8);
    height: 54px;
    width: 54px;
    line-height: 54px;
    font-size: 14px;
    text-align: center;
    color: #fff;
    position: absolute;
    z-index: 1;
    top: 0;
    cursor: pointer;
    border-radius: 50%;
  }
.cropper-shadow {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 9999;
}
.cropper-img {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 720px;
  height: 530px;
  background-color: #FFFFFF;
  border-radius: 5px;
  z-index: 10000;
  .cropper-close {
    float: right;
    margin-right: 15px;
    margin-top: 15px;
    width: 20px;
    height: 20px;
  }
  .cropper-left {
    margin-left: 40px;
    margin-top: 40px;
    width: 400px;
    height: 400px;
  }
  .cropper-right {
    margin-top: 40px;
    margin-left: 40px;
    .cropper-region {
      width: 200px;
      height: 200px;
      border-radius: 50%;
      border: 1px solid #ebebeb;
    }
  }
  .btn-box {
    display: flex;
    margin-top: 40px;
    justify-content: center;
    .btn-left {
      width: 64px;
      height: 33px;
      border: 1px solid #ebebeb;
      border-radius: 2px;
      background-color: #FFFFFF;
      text-align: center;
      line-height: 33px;
    }
    .btn-right {
      margin-left: 25px;
      width: 64px;
      height: 33px;
      border: 1px solid #2875E8;
      border-radius: 2px;
      background-color: #2875E8;
      text-align: center;
      line-height: 33px;
      color: #FFFFFF;
    }
  }
}
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值