vue项目中使用vue-cropper实现裁剪、上传到oss接口

标签: Vue.js

效果图:

实现步骤:

1,项目中添加vue-cropper插件 :npm install vue-cropper --save   或者 yarn add vue-cropper --save

2,在main.js中引入一下:

import VueCropper from 'vue-cropper' 

Vue.use(VueCropper)

3,.vue文件内容:

<template>
  <div style="width:1200px;margin:12px auto 0 auto;display:flex;justify-content:space-between;">
    <!-- 头像区域 -->
    <a-card style="width:260px;">
      <!-- 头像 -->
      <a-avatar :size="80" :src="src2" 
style="margin:0 auto;display:flex;" @click="myPortrait"/>
      <!-- <a-avatar :size="80" :src="avatar()?avatar():src" 
style="margin:0 auto;display:flex;" @click="myPortrait"/> -->
      <!-- 修改密码按钮 -->
      <a-row>
        <a-col :span="24" 
style="font-size:12px;color:#767885;display:flex;justify-content:center;">
          <a-button @click="alertPassword">修改密码</a-button>
        </a-col>
      </a-row>
    </a-card>
    <!-- 修改头像弹窗 -->
      <a-modal title="修改头像" v-model="visible2" :footer="null" 
:bodyStyle="{padding:0}" @cancel="resetForm">
      <a-row style="padding:24px 24px 16px 24px;margin:0;">
        <a-col :span="16">
          <div class="cropper">
            <vueCropper
              ref="cropper"
              :img="option.img"
              :outputSize="option.size"
              :outputType="option.outputType"
              :info="option.info"
              :full="option.full"
              :canMove="option.canMove"
              :canMoveBox="option.canMoveBox"
              :original="option.original"
              :autoCrop="option.autoCrop"
              :autoCropWidth="option.autoCropWidth"
              :autoCropHeight="option.autoCropHeight"
              :fixedBox="option.fixedBox"
              @realTime="realTime"
            ></vueCropper>
          </div>
        </a-col>
        <a-col :span="8" style="text-align: center;">
          <div class="preview">
            <!-- <div :style="previews.div" class="preview"> -->
            <img :src="previews.url" :style="previews.img" />
          </div>
          <div style="text-align:center;">头像预览</div>
        </a-col>
      </a-row>
      <a-row style="padding:0 0 8px 24px;margin:0;">
        <a-col :span="24">
          <label class="btn" for="uploads" style="color:#3264D5;">上传头像</label>
          <input
            type="file"
            id="uploads"
            :value="imgFile"
            style="position:absolute; clip:rect(0 0 0 0);width: 1px;"
            accept="image/png, image/jpeg, image/gif, image/jpg"
            @change="uploadImg($event, 1)"
          />
        </a-col>
      </a-row>
      <a-row>
        <a-col
          :span="24"
          style="display:flex;justify-content:center;border-top:1px solid #e8e8e8;padding:14px 0;"
        >
          <a-button type="primary" @click="submitForm" style="background:#3264D5;">确定</a-button>
          <a-button style="margin-left: 10px" @click="resetForm">取消</a-button>
        </a-col>
      </a-row>
    </a-modal> 
  </div>
</template>
<script>
import { baseUrl } from '@/api/manage'
import { uploadImage } from '@/api/api'  // 引入接口
export default {
  data() {
    return {
      src2:'', 
      src: '../../assets/tx.png', // 头像默认地址
      visible: false, // 修改密码弹窗是否显示的标志
      labelCol: { span: 4 },
      wrapperCol: { span: 14 }, 
       visible2: false,
      //剪切图片上传
      previews: {},
      option: {
        img: "", // 裁剪图片的地址
        outputSize: 1, // 裁剪生成图片的质量
        outputType: "png", // 裁剪生成图片的格式
        info: true, // 裁剪框的大小信息
        canScale: false, // 图片是否允许滚轮缩放
        // autoCrop: false, // 是否默认生成截图框
        autoCrop: true, // 是否默认生成截图框
        autoCropWidth: 120, // 默认生成截图框宽度
        autoCropHeight: 120, // 默认生成截图框高度
        fixedBox: true, // 固定截图框大小 不允许改变
        fixed: true, // 是否开启截图框宽高固定比例
        fixedNumber: [1, 1], // 截图框的宽高比例
        canMove: true, // 上传图片是否可以移动
        canMoveBox: true, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: true, // 截图框是否被限制在图片里面
        infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        full: false, // 是否输出原图比例的截图
        enlarge: 0.5, // 图片根据截图框输出比例倍数
        mode: "contain" // 图片默认渲染方式 
      },
      fileName: "", // 本机文件地址
      downImg: "#",
      imgFile: "", 
    }
  },
  /* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
  created() { 
  },
  computed: {},
  methods: {   
    // 点击我的头像触发
    myPortrait(){
        this.visible2 = true;
    },  
    // 点击修改头像弹窗的确定按钮触发
  submitForm() {
      this.$refs.cropper.getCropData((data) => {
       // 拿到的data 其实是base64格式的图片
        var blob = this.dataURItoBlob(data); // 调用方法将base64格式的转为二进制大对象格式
        var fd = new FormData();
        fd.append("file", blob);
        fd.append("ossModuleCode","image")
        // 该接口用于上传图片;后台要求的是 formData 格式的,所以将blob放入FormData;下面的接口根据自己需要进行更改
        uploadImage(fd).then(res=>{
// 接口返回的res.data.imgUrl 是一个图片的链接,以 .blob格式结尾的;放入img标签的src可以显示图片
            this.src2 = res.data.imgUrl
          })
      }) 
    },
// 该方法将base64格式的图片转换为blob格式;blob:二进制大对象
   dataURItoBlob(base64Data) {
    var byteString;
    if (base64Data.split(',')[0].indexOf('base64') >= 0){
        byteString = atob(base64Data.split(',')[1]);
    }else{
        byteString = unescape(base64Data.split(',')[1]);
    }
    var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia], {type:mimeString});
},
    // 点击修改头像弹窗的取消按钮触发
    resetForm() {
        this.visible2 = false;
        setTimeout(()=>{
          this.option.img = '';
        },500)
    },  
    // 实时预览函数
    realTime(data) {
      this.previews = data;
    }, 
    // 选择本地图片
    uploadImg(e, num) {
      var _this = this;
      // 上传图片
      var file = e.target.files[0];
      _this.fileName = file.name;
      if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
//改提示使用了ant-design-vue中的提示框,项目中需要引入ant-design-vue,不想使用该提示可以注释,使用alert()
        this.$message.warning("图片类型必须是.gif,jpeg,jpg,png,bmp中的一种")
        return false;
      }
      var reader = new FileReader();
      reader.onload = e => {
        let data;
        if (typeof e.target.result === "object") {
          // 把Array Buffer转化为blob 如果是base64不需要
          data = window.URL.createObjectURL(new Blob([e.target.result]));
        } else {
          data = e.target.result;
        }
        if (num === 1) {
          _this.option.img = data;
        } else if (num === 2) {
          _this.example2.img = data;
        }
      };
      // 转化为base64
      // reader.readAsDataURL(file)
      // 转化为blob
      reader.readAsArrayBuffer(file);
    },
  }
}
</script>
<style lang="scss" scoped>
.col-3 { color: #767885; font-size: 14px;  text-align: right; }
.col-6 { color: #3c3d43; font-size: 14px; padding-left: 24px; font-weight: 500; }
.password { text-align: right; }
.password2 {  padding-left: 16px; }
.ant-row { margin: 16px 0; }
.cropper {  width: 100%; height: 300px; }
.preview { width: 120px; height: 120px;  border-radius: 50%; 
border: 1px solid #ccc; background-color: #ccc; margin: 5px; overflow: hidden; 
display: inline-block; }
</style>

 

版权声明:本文为yinge0508原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yinge0508/article/details/106014177

智能推荐

mybatis+ehcache二级缓存

导入jar包 mapper.xml文件开启二级缓存 pojo类实现序列化接口 配置ehcache.xml 测试...

python+opencv实现图像拼接

任务 拍摄两张图片去除相同部分,拼接在一起 原图 结果 步骤 读取两张图片 使用sift检测关键点及描述因子 匹配关键点 处理并保存关键点 得到变换矩阵 图像变换并拼接 代码实现 扩展 这里对右边图像进行变换,右边变得模糊,可以修改代码对左边图像变换 这里只有两张图片拼接,可以封装实现多张图片拼接 可以修改代码实现上下图片的拼接...

python_sklearn机器学习算法系列之AdaBoost------人脸识别(PCA,决策树)

          注:在读本文之前建议读一下之前的一片文章python_sklearn机器学习算法系列之PCA(主成分分析)------人脸识别(k-NearestNeighbor,KNN)         本文主要目的是通过一个简单的小...

memmove函数与memcpy函数的模拟实现

memmove函数和memcpy函数都是在内存复制任意类型的,但是它俩也有区别。当源区域和目标区域有重复的,memmove函数会复制缓冲区重叠的部分,而memcpy相反,会报出未知错误。 下面给出两个函数的实现 首先,memmove函数。 实现的基本原理如下图。 具体代码如下: memcpy函数的实现很简单,就直接给出源代码了...

猜你喜欢

SpringFramework核心 - IOC容器的实现 - 总结

1. 概述 把Spring技术内幕第一章和第二章过了一遍,也做了一些笔记, 对IOC容器的实现有了一定皮毛理解,现在跟着源码再过一遍总结一下IOC容器的初始化,Bean的初始化的过程,做一下总结 ① IOC容器和简单工厂模式 在开始之前,先想想我们平时是怎么使用IOC容器为我们管理Bean的,假设我们要把下面的User类交给IOC容器管理 我们不想关心如何创建一个User对象实例的,仅仅在需要他的...

Python和Django的安装

个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈  一、下载并安装Python Python 官方下载地址:http://www.python.org/ftp/python/ 我们这里选择的是 Python 2.7.2 。虽然目前最新版是Python 3.2.2, 但是Django目前还不支持 Python 3.2.2。 安装步骤很简单,双击安装包开...

OpenStack代码贡献初体验

为什么80%的码农都做不了架构师?>>>     OpenStack如今已成为开源云平台中的明星项目,得到广泛关注。OpenStack的优秀出众依赖于众多开发者的努力,在享受其带来的便利与快捷的同时,为其做一份贡献也是一个开发者的义务。  在前段时间的OpenStack的测试过程中,我发现Nova项目中的一个Bug,于是向社区提交了Bug报...

SQL Server之8:sql查询每个学生得分最高的两门课

这是一道面试题,今天有空把它记下来,以后遇到此类问题作个参考!刚一看到这个题目,估计好多人都会想到关键字top,其实这里用到的关键字是partition, 好了,先看看表结构,及数据吧!     接下来看一看partition的功能,执行语句   结果如下:   到这里一目了然知道最终结果了!   View Code     &...

vue-video-player 浏览器缩放

文章目录 前言 一、vue-video-player的封装 二、调用 1. 引入 2. vue template代码 2. 主要js代码 效果 前言 此篇是在上一次《[Vue 播放rtmp直播流]》基础之上的更新及补充;近期接到客户需求,需要在视频流上显示额外的信息;当然,视频流上叠加信息可以通过canvas来完成(透明canvas实现),但是在测试的过程中发现,当浏览器缩放时,叠加的图层信息与初...