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

18 篇文章 1 订阅
13 篇文章 0 订阅

移动端vue使用vant上传图片并裁剪:
效果图如下:
在这里插入图片描述

使用到的组件: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 VantUploader组件可以很方便地实现上传、压缩和旋转图片功能。首先,我们需要在Vue项目中引入Vue Vant库,并在需要使用Uploader的组件中注册该组件。 在页面中使用Uploader组件时,我们可以设置相关的属性来实现功能需求。首先是上传图片功能,可以通过设置`action`属性来指定图片上传的后端接口地址。上传成功后,可以通过监听`@success`事件来处理上传成功的逻辑,例如显示上传成功的提示信息或者将上传成功的图片URL保存到数据库等。 对于压缩图片的功能,我们可以使用该组件提供的`beforeRead`方法来获取用户要上传的图片文件对象。然后,利用`HTMLCanvasElement`的`toBlob`方法对图片进行压缩,并将压缩后的图片对象传给Uploader组件进行上传。在压缩图片时,可以设置压缩的尺寸或者压缩的质量、压缩比等参数,以控制压缩后的图片大小适应实际需求。 要实现图片旋转的功能,我们可以利用`EXIF.js`库来读取图片的EXIF信息,获取图片的拍摄方向。然后,根据拍摄方向来确定图片需要旋转的角度,再借助`canvas`的`rotate`方法对图片进行旋转。旋转后的图片可以在`@success`事件触发后重新渲染到页面上,或者直接发送到后端进行保存。 总结来说,移动端Vue VantUploader组件通过设置相关属性和监听事件,配合压缩工具和EXIF库,可以非常方便地实现图片上传、压缩和旋转功能,满足移动端图片处理的需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值