移动端vue使用vant上传图片并裁剪

移动端vue使用vant上传图片并裁剪:
效果图如下:
移动端vue使用vant上传图片并裁剪_第1张图片

使用到的组件:vueCropper,van-popup,van-uploader
首先基于vueCropper封装了一个子组件页面:ImageCropper.vue

<template>
	<!-- 剪裁图片组件 -->
    <van-popup
      class="bg-tran image-cropper"
      v-model="visible"
      closeable
      position="top"
      :lock-scroll="false"
      :style="{ height: '100%' }"
    >
      <div class="flex-column-center height100">
        <vueCropper
          ref="imageCropper"
          :img="url"
          :outputSize="option.outputSize"
          :outputType="option.outputType"
          :info="option.info"
          :full="option.full"
          :autoCropWidth="option.autoCropWidth"
          :autoCropHeight="option.autoCropHeight"
          :canMove="option.canMove"
          :canMoveBox="option.canMoveBox"
          :original="option.original"
          :autoCrop="option.autoCrop"
          :fixed="option.fixed"
          :fixedNumber="option.fixedNumber"
          :centerBox="option.centerBox"
          :infoTrue="option.infoTrue"
          :fixedBox="option.fixedBox"
          :high="option.high"
          :mode="option.mode"
        ></vueCropper>
        <van-col span="24" class="font14 col-white">
          <van-col span="8" class="p-2" @click="onCancel"><span>取消</span></van-col>
          <van-col span="8" class="p-2 text-center" @click="rotateImage"><span class="font18"><van-icon name="replay" /></span></van-col>
          <van-col span="8" class="p-2 text-right" @click="onConfirm"><span>确定<i class="el-icon-loading" v-if="loading"></i></span></van-col>
        </van-col>
      </div>
    </van-popup>
</template>
<script>
import {
  //随机字符串
  randomString as utilRandomString
} from "@/utils/utility";
import { VueCropper } from 'vue-cropper';
const COS = require('cos-js-sdk-v5');

export default {
  components: {
    VueCropper,
  },
  props: {
    visible: Boolean, //控制是否显示
    url: String //裁剪的图片
  },
	data() {
		return {
	      loading: false,
	      option: {
	        outputSize: 0.8,
	        info: false, // 裁剪框的大小信息
	        outputType: 'jpeg', // 裁剪生成图片的格式
	        canScale: false, // 图片是否允许滚轮缩放
	        autoCrop: true, // 是否默认生成截图框
	        autoCropWidth: window.innerWidth - 100 + 'px', // 默认生成截图框宽度
	        autoCropHeight: window.innerWidth - 100 + 'px', // 默认生成截图框高度
	        high: true, // 是否按照设备的dpr 输出等比例图片
	        fixedBox: true, // 固定截图框大小 不允许改变
	        fixed: true, // 是否开启截图框宽高固定比例
	        fixedNumber: [1, 1], // 截图框的宽高比例
	        full: true, // 是否输出原图比例的截图
	        canMoveBox: false, // 截图框能否拖动
	        original: false, // 上传图片按照原始比例渲染
	        centerBox: false, // 截图框是否被限制在图片里面
	        infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
	        mode: '100% auto' // 图片默认渲染方式
	      }
		}
	},
  methods: {
    rotateImage() {
      //旋转图片
      this.$refs.imageCropper.rotateRight();
    },
    onCancel() {
      //取消
      this.$emit('cancel');
    },
    onConfirm() {
      //确定
      if(this.loading) {
        return ;
      }
      this.loading = true;
      this.$refs.imageCropper.getCropBlob((file) => {
		//此时可以拿file进行文件上传了,以下为腾讯云COS的上传demo,可以改为自己的上传方式
        this.handleChange(file).then((data)=>{
          //上传成功 执行回调
          this.$emit('success', file);
          this.loading = false;
          //请求接口,更新头像操作
        }, (error) => {
          this.loading = false;
        });
      });
    },
    handleChange(file) {
      //文件上传
      return new Promise((resolve, reject)=>{
        //获取腾讯云COS临时密钥
        axios("xxxxx", "get", {
          fileType: 'file'
        })
        .then((response) => {
          var credentials = response.credentials;
          var cos = new COS({
            getAuthorization: function (options, callback) {
              callback({
                TmpSecretId: credentials.tmpSecretId,
                TmpSecretKey: credentials.tmpSecretKey,
                SecurityToken: credentials.sessionToken,
                StartTime: credentials.startTime, // 时间戳,单位秒
                ExpiredTime: credentials.expiredTime, // 过期时间 时间戳
              })
            },
          })
          // 上传文件
          cos.putObject({
            Bucket: 'xxxx', //存储桶
            Region: 'xxxx', //存储桶所在地域
            Key: 'xxxx', //在前面加上路径写法可以生成文件夹
            StorageClass: 'xxxx', //设置对象的存储类型,枚举值
            Body: file, //上传文件对象
          }, (error, data) => {
            if(error == undefined) {
              //返回数据
              resolve(data)
            }else {
              //返回异常
              reject(error);
            }
          })
        })
        .catch((error) => {
          reject(error);
        });
      })
    }
  }
}
</script>
<style>
.image-cropper .height100 {
	height: 100vh;
}
.image-cropper .flex-column-center { 
	display: flex;
	flex-flow: column;
	justify-content: center;
	align-items: center;
}
.image-cropper .vue-cropper {
  background: #000;
}
.image-cropper .vue-cropper .cropper-view-box {
  outline: 1px solid #fff !important;
  outline-color: #fff !important;
}
.image-cropper .van-col {
  height: 50px;
  line-height: 50px;
  margin-bottom: 30px;
}
.image-cropper .van-col .el-icon-loading {
  margin-left: 5px;
}
</style>

父页面引入方式如下

<template>
  <div class="my-info">
    <div>上传图片裁剪</div>
    <img :src="avatarUrl" />
    <van-uploader :before-read="beforeRead" :after-read="afterRead" accept="image/png, image/jpeg" :max-size="1024 * 1024 * 11" @oversize="onOversize">
      <van-button type="primary">上传头像</van-button>
    </van-uploader>
    <image-cropper
      :visible="cropperVisible"
      :url="imgUrl"
      :file-info="fileInfo"
      @cancel="cropperVisible = false"
      @success="cropperSuccess"
    />
  </div>
</template>
<script>
import ImageCropper from '@/components/ImageCropper'
import { Toast } from 'vant';
export default {
  components: { ImageCropper },
  data() {
    return {
      fileInfo: {},
      imgUrl: '',
      avatarUrl: require('@/assets/img/default-avatar.png'), //默认头像
      cropperVisible: false
    };
  },
  methods: {
    onOversize() {
      Toast('图片大小不能超过10M');
    },
    beforeRead(file) {
      if (file.type !== 'image/png' && file.type !== 'image/jpeg') {
        Toast('请上传图片');
        return false;
      }
      return true;
    },
    cropperSuccess(file) {
      //裁剪上传完成
      this.avatarUrl = 'https://' + file.location;
      this.cropperVisible = false;
      //请求保存头像操作
      axios("/upload/xxxx", "post", {})
      .then((response) => {
        Toast('上传头像成功');
      })
      .catch((error) => {
        Toast('上传头像失败,请重试');
      });
    },
    afterRead(file) {
      //图片加载完成 进行裁剪
      file = file.file;
      const fileReader = new FileReader();
      fileReader.readAsDataURL(file);
      fileReader.onload = () => {
        //显示裁剪框
        this.imgUrl = fileReader.result;
        //将文件信息传过去
        this.fileInfo = {
          name: file.name,
          suffix: file.name.substring(file.name.lastIndexOf(".") + 1)
        };
        this.cropperVisible = true;
      };
    }
  },
};
</script>

这样就大功告成了!

你可能感兴趣的:(Vue.js,技术开发,H5,vue.js,前端,javascript)