vue实现图片裁剪后上传

本文实例为大家分享了vue实现图片裁剪后上传的具体代码,供大家参考,具体内容如下

一、背景

目前负责的系统(商城后台管理系统)里面有这么一个需求,为了配合前台的展示,上传的商品图片比较必须是1:1的正方形。(其它地方有时会有5:4或者16:9的需求,但较少)。所以需要对上传的图片先进行裁剪,并且按要求只能裁剪为1:1,然后在进行上传。

当然,为了兼容系统其它地方有5:4或者16:9的图片比例需求,需要给出一个参数,可以随时控制图片裁剪的比例。

二、使用什么插件实现

使用 vue-cropper 显示,该插件是基于 cropper 的二次封装,简单小巧,更合适vue项目。注意:功能没有 cropper 强大。

三、使用 cropper

3.1 封装一下cropper, 配置自己想要的参数

<template>
 <div class="Cropper">
 <el-dialog
  :visible.sync="dialogVisible"
  width="740px"
  title="图片裁剪"
  :before-close="handleClose"
  :close-on-click-modal="false">
  <div
  class="cropper-container">
  <div class="cropper-el">
   <vue-cropper
   ref="cropper"
   :img="cropperImg"
   :output-size="option.size"
   :output-type="option.outputType"
   :info="true"
   :can-move="option.canMove"
   :can-move-box="option.canMoveBox"
   :fixed-box="option.fixedBox"
   :auto-crop="option.autoCrop"
   :auto-crop-width="option.autoCropWidth"
   :auto-crop-height="option.autoCropHeight"
   :center-box="option.centerBox"
   :high="option.high"
   :info-true="option.infoTrue"
   @realTime="realTime"
   :enlarge="option.enlarge"
   :fixed="option.fixed"
   :fixed-number="option.fixedNumber"
   :limitMinSize="option.limitMinSize"
   />
  </div>
  <!-- 预览 ==>> 我不需要预览 -->
  <!-- <div class="prive-el">
   <strong>预览:</strong>
   <div class="prive-style" :style="{'width': '200px', 'height': '200px', 'overflow': 'hidden', 'margin': '10px 25px', 'display':'flex', 'align-items' : 'center'}">
   <div class="prive-style" :style="{'width': previews.w + 'px', 'height': previews.h + 'px', 'overflow': 'hidden', 'margin': '10px 25px', 'display':'flex', 'align-items' : 'center'}">
   <div class="preview" :style="previews.div">
    <img :src="previews.url" :style="previews.img">
   </div>
   </div>
   <el-button @click="uploadBth">重新上传</el-button>
  </div> -->
  </div>
  <span
  slot="footer"
  class="dialog-footer">
  <el-button @click="uploadBth">重新上传</el-button>
  <el-button
   @click="handleClose">取 消</el-button>
  <el-button
   type="primary"
   @click="saveImg">确 定</el-button>
  </span>
 </el-dialog>
 </div>
</template>

<script>
import { VueCropper } from 'vue-cropper';
export default {
 name: 'Cropper',
 components: {
 VueCropper
 },
 props: {
 dialogVisible: {
  type: Boolean,
  default: false
 },
 imgType: {
  type: String,
  default: 'blob'
 },
 cropperImg: {
  type: String,
  default: ''
 },
 zoomScale: {  // 裁剪比例,默认1:1
  type: Array,
  default: [1, 1]
 }
 },
 data () {
 return {
  previews: {},
  option: {
  img: '', // 裁剪图片的地址
  size: 1, // 裁剪生成图片的质量
  outputType: 'png', // 裁剪生成图片的格式 默认jpg
  canMove: false, // 上传图片是否可以移动
  fixedBox: false, // 固定截图框大小 不允许改变
  canMoveBox: true, // 截图框能否拖动
  autoCrop: true, // 是否默认生成截图框
  // 只有自动截图开启 宽度高度才生效
  autoCropWidth: 500, // 默认生成截图框宽度
  autoCropHeight: 500, // 默认生成截图框高度
  centerBox: true, // 截图框是否被限制在图片里面
  high: false, // 是否按照设备的dpr 输出等比例图片
  enlarge: 1, // 图片根据截图框输出比例倍数
  mode: 'contain', // 图片默认渲染方式
  maxImgSize: 2000, // 限制图片最大宽度和高度
  // limitMinSize: [500,500], // 更新裁剪框最小属性
  limitMinSize: 500, // 更新裁剪框最小属性
  infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  fixed: true, // 是否开启截图框宽高固定比例 (默认:true)
  // fixedNumber: [1, 1] // 截图框的宽高比例 ==>> 这个参数目前没有作用(作者解释的)
  fixedNumber: this.zoomScale // 截图框的宽高比例
  },
 };
 },
 methods: {
 // 裁剪时触发的方法,用于实时预览
 realTime (data) {
  this.previews = data;
 },
 // 重新上传
 uploadBth () {
  this.$emit('update-cropper');
 },
 // 取消关闭弹框
 handleClose () {
  this.$emit('colse-dialog', false);
 },
 // 获取裁剪之后的图片,默认blob,也可以获取base64的图片
 saveImg () {
  if (this.imgType === 'blob') {
  this.$refs.cropper.getCropBlob(data => {
   this.$emit('upload-img', data);
  });
  } else {
  this.$refs.cropper.getCropData(data => {
   this.uploadFile = data;
   this.$emit('upload-img', data);
  });
  }
 }
 }
};
</script>

<style lang="scss" scoped>
.Cropper {
 .cropper-el {
 height: 700px;
 width: 700px;
 flex-shrink: 0;
 }
 .cropper-container {
 display: flex;
 justify-content: space-between;
 .prive-el {
  flex: 1;
  align-self: center;
  text-align: center;
  .prive-style {
  margin: 0 auto;
  flex: 1;
  -webkit-flex: 1;
  display: flex;
  display: -webkit-flex;
  justify-content: center;
  -webkit-justify-content: center;
  overflow: hidden;
  background: #ededed;
  margin-left: 40px;
  }
  .preview {
  overflow: hidden;
  }
  .el-button {
  margin-top: 20px;
  }
 }
 }
}
</style>
<style lang="scss">
.cropper-box-canvas img{
 width: 100% !important;
 height: 100% !important;
}
</style>

3.2 将 el-upload 和 cropper 组合,封装,其他地方可以直接调用

<template>
 <div>
 <!-- 注意:必须关闭自动上传属性 auto-upload -->
 <el-upload
  :http-request="Upload"
  :multiple="true"
  list-type="picture-card"
  :file-list="productImageList"
  :on-remove="removeImage"
  :limit="12"
  :before-upload="beforeAvatarUpload"
  ref="fileUpload"
  :auto-upload="false"
  :on-change="selectChange"
  action=""
  class="cropper-upload-box"
 >
  <i slot="default" class="el-icon-plus"></i>
 </el-upload>

 <cropper
  v-if="showCropper"
  :dialog-visible="showCropper"
  :cropper-img="cropperImg"
  :zoomScale="zoomScale"
  @update-cropper="updateCropper"
  @colse-dialog="closeDialog"
  @upload-img="uploadImg"
 />
 </div>
</template>

<script>
import Cropper from "@/components/cropper";
import { client, randomWord } from '@/utils/alioss'
export default {
 name: "CropperUpload",
 data() {
 return {
  productImageList: [],

  showCropper: false, // 是否显示裁剪框
  cropperImg: "" // 需要裁剪的图片
 };
 },
 props: {
 defaultImgList: {  // 默认显示的图片列表
  type: Array,
  default: () => []
 },
 zoomScale: {   // 裁剪比例,默认1:1
  type: Array,
  default: [1, 1]
 }
 },
 components: {
 Cropper
 },
 watch: {
 defaultImgList: {
  handler: function(newVal, oldVal){
  this.productImageList = newVal // 赋值
  },
  deep: true
 }
 },
 methods: {
 beforeAvatarUpload(file) {
  const isLt2M = file.size / 1024 / 1024 < 2;  // 原图片
  // const isLt2M = this.uploadFile.size / 1024 / 1024 < 1;  //裁剪后的图片(会比原图片大很多,应该是转成Blob的原因导致)
  if (!isLt2M) {
  this.$message.error("上传图片大小不能超过 2MB!");
  this.noCanUpload = true  // 如果这里被拦截,将自动删除不能上传的图片
  return false
  }
  // return isLt2M
 },
 removeImage(file, fileList) {
  const index = this.productImageList.findIndex(item => {
  return item.uid == file.uid;
  });
  if (index > -1) {
  this.productImageList.splice(index, 1);
  }
  this.$emit('getUploadImg', this.productImageList) // 把最新上传的图片列表返回
 },
 Upload(file) {
  var fileName = `img/${randomWord(
  true,
  20
  )}${+new Date()}${file.file.name.substr(file.file.name.indexOf("."))}`;
  // client().put(fileName, file.file).then(result => {
  client()
  .put(fileName, this.uploadFile)
  .then(result => {
   // 上传裁剪后的图片
   console.log(result);
   this.productImageList.push({
   url: result.url,
   uid: file.file.uid,
   saveUrl: "/" + result.name
   });
   this.showCropper = false;
   this.$emit('getUploadImg', this.productImageList) // 把最新上传的图片列表返回
  })
  .catch(err => {
   this.showCropper = false;
   console.log(err);
  });
 },

 // 更新图片
 updateCropper() {
  if(!this.noCanUpload){
  let fileList = this.$refs.fileUpload.uploadFiles  // 获取文件列表
  let index02 = fileList.findIndex(item => {  // 把取消裁剪的图片删除
   return item.uid == this.currentFile.uid;
  });
  fileList.splice(index02, 1)
  }

  let index = this.$refs.fileUpload.$children.length - 1;
  this.$refs.fileUpload.$children[index].$el.click();
 },
 // 关闭窗口
 closeDialog() {
  this.showCropper = false;

  if(!this.noCanUpload){
  let fileList = this.$refs.fileUpload.uploadFiles  // 获取文件列表
  let index = fileList.findIndex(item => {  // 把取消裁剪的图片删除
   return item.uid == this.currentFile.uid;
  });
  fileList.splice(index, 1)
  }
 },
 // 上传图片
 uploadImg(file) {
  this.uploadFile = file;
  // this.$refs.fileUpload.submit();

  // 判断裁剪后图片的宽高
  let img = new Image()
  img.src = window.URL.createObjectURL(file);  // Blob转成url 才能给img显示
  img.onload = () => {
  let minProp = Math.min(img.width, img.height) //裁剪后的图片宽,高 ==> 取最小值
  if( minProp < 500){  // 如果最小值比设置的最小值(默认为500)小
   this.$message.error(`请保证图片短边最小为500`);
   return false
  }
  this.$refs.fileUpload.submit();
  }
 },
 selectChange(file) {
  this.noCanUpload = false
  let files = file.raw;
  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;
  }
  this.cropperImg = data;

  // 图片图片尺寸,如果是正方形,则直接上传;否则调用裁剪
  let img = new Image()
  img.src = this.cropperImg;
  img.onload = () => {
   if(img.width == img.height){ // 本来就是正方形 => 直接上传
   this.uploadFile = files;
   this.$refs.fileUpload.submit(); // 调用上传方法
   }else{
   this.showCropper = true;  // 不是正方形的图片才开启裁剪
   this.currentFile = file  // 保存当前操作裁剪的图片
   }
  }
  };
  // 转化为base64
  // reader.readAsDataURL(file)
  // 转化为blob
  reader.readAsArrayBuffer(files);

  // this.showCropper = true;  // 默认开启裁剪
 }
 }
};
</script>

<style lang="scss">
.cropper-upload-box{
 display: flex;
 .el-upload{
 width: 148px;
 height: 148px;
 }
}
</style>

3.3 其他页面中调用裁剪组件

<!--
 zoomScale:定义的裁剪比例;
 defaultImgList: 默认显示的图片列表
 @getUploadImg:这个事件将得到更新后(上传、删除)的图片列表,在页面中重新赋值给默认的列表变量后就可以做页面中的逻辑处理了
 -->
<cropper-upload :zoomScale='[1,1]' :defaultImgList="productImageList" @getUploadImg="getUploadImg"></cropper-upload>

自此,图片裁剪功能实现!!!

3.4 看一下页面中的效果

​​​​​​​以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue+vant 上传图片需要注意的地方

    <van-uploader v-model="fileList" multiple :after-read="afterRead" :max-count="1" /> 1:上传文件流,提交的模式 肯定得 form-data模式 2:上传的文件file 做出处理我这里做的只能选择一张 afterRead(file){ console.log(file); //控制台可以看见图片信息 if(this.fileList.length >

  • 移动端 Vue+Vant 的Uploader 实现上传、压缩、旋转图片功能

    面向百度开发 html <van-uploader :after-read="onRead" accept="image/*"> <img src="./icon_input_add.png" /> </van-uploader> js data() { return { files: { name: "", type: "" }, headerImage: null,

  • vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)

    说在前面 网上有很多种文件上传的方法,根据公司最近的业务需求,要求实现多种文件的上传,在实现过程中,查阅了很多资料,最后,终于把功能实现了,开心! <template> <div> <v-header :left-text="`上传${columnName}`"></v-header> <div class="upload"> <div v-if="columnName === '视频'&q

  • vue 图片裁剪上传组件的实现

    先看一下总体效果: 上传文件做了大小和类型的限制,在动图中无法展现出来. 使用file类型的input实现选择本地文件 但是浏览器原生的文件上传按钮的颜值不尽人意,而且按钮上的文字是无法改变的,我需要把这个上传文件的按钮改造一下. 方法1:使用label元素来触发一个隐藏的file类型的 input元素:(缺点:在多人开发时,可能出现重复的元素id,导致难以预料的bug) <input type="file" id='up_file_input' v-show='false' &

  • vue+element实现图片上传及裁剪功能

    本文实例为大家分享了vue+element实现图片上传及裁剪的具体代码,供大家参考,具体内容如下 随便写的一个小demo 功能是没有任何问题 可能里面会有一些小细节没有优化 1 .安装 vue-cropper npm install vue-cropper 2.组件内使用 import { VueCropper } from 'vue-cropper' components: { VueCropper, }, 具体可见官网 demo <template> <div> <h1&

  • vue在图片上传的时候压缩图片

    需求: 上传到服务器的图片太大会导致服务器承受不了,故在前端传图片的时候将图片压缩后再传到服务器 直接上代码 async getRealName(){ let nickname = this.nickname.trim() let idnum = this.idnum.trim() let nameReg = /[\u4e00-\u9fa5]/gm let idnumReg = /^[a-z0-9]+$/i let zheng1 = document.getElementById("file1&

  • Vue+Vant 图片上传加显示的案例

    前端开发想省时间就是要找框架呀!找框架! vant中上传图片组件:https://youzan.github.io/vant/#/zh-CN/uploader 上传图片的组件uploader: <van-uploader :after-read="onRead" accept="image/*" multiple> <imgclass="head-img" src="/static/images/addpic.png&

  • vue 使用微信jssdk,调用微信相册上传图片功能

    vue 使用微信jssdk 1.引入weixin-js-sdk npm install weixin-js-sdk 使用文档 https://www.npmjs.com/package/weixin-js-sdk 2.配置 vue中微信jssdk配置 import wx from 'weixin-js-sdk' created(){ //微信jssdk配置 let timestamp=new Date().getTime();//时间戳 let noncestr=Math.random().to

  • vue-quill-editor 自定义工具栏和自定义图片上传路径操作

    背景: 1.某些场景下vue-quill-editor默认的工具栏部分功能不希望出现,需要删除部分功能. 2.vue-quill-editor默认提供的图片上传方案是将图片转成base64存放到内容区,这会导致content字符长度太长,不一定可以传到后台保存(其实即使可以保存也不推荐这种方案).所以我们需要将方案修改为将图片上传到服务器,然后通过URL的 方式访问到图片回显及使用. vue-quill-editor工具栏改造及自定义图片上传(这里使用的是element-ui的上传组件): 引入

  • vue实现图片裁剪后上传

    本文实例为大家分享了vue实现图片裁剪后上传的具体代码,供大家参考,具体内容如下 一.背景 目前负责的系统(商城后台管理系统)里面有这么一个需求,为了配合前台的展示,上传的商品图片比较必须是1:1的正方形.(其它地方有时会有5:4或者16:9的需求,但较少).所以需要对上传的图片先进行裁剪,并且按要求只能裁剪为1:1,然后在进行上传. 当然,为了兼容系统其它地方有5:4或者16:9的图片比例需求,需要给出一个参数,可以随时控制图片裁剪的比例. 二.使用什么插件实现 使用 vue-cropper

  • struts2+jsp+jquery+Jcrop实现图片裁剪并上传实例

    今天有业务需要制作用户头像的需求,在网上找了个可以裁剪大图制作自己希望大小的图片的方法(基于Struts2).特此记录一下. 不废话,具体的步骤如下: <1> 使用html标签上传需要裁剪的大图. <2> 在页面呈现大图,使用Jcrop(Jquery)对大图进行裁剪,并且可以进行预览. <3> 选择好截取部分之后发送数据给Action,在服务器端使用 Java API 对大图进行裁剪. <4> 保存大图裁剪好的头像到指定目录,完成业务. 下面一步一步做: 第

  • 基于HTML5+JS实现本地图片裁剪并上传功能

    最近做了一个项目,这个项目中需要实现的一个功能是:用户自定义头像(用户在本地选择一张图片,在本地将图片裁剪成满足系统要求尺寸的大小).这个功能的需求是:头像最初剪切为一个正方形.如果选择的图片小于规定的头像要求尺寸,那么这整张图片都会作为头像.如果大于规定的尺寸,那么用户可以选择要裁剪的区域.用户点击确定按钮,就将裁剪得到的图片数据发送到服务器,在后端将图片数据保存成一个文件. 要完成上述功能,涉及到的知识有:ajax,canvas和html5中的files接口.我将实现这个功能的代码封装到了4

  • vue.js 实现图片本地预览 裁剪 压缩 上传功能

    以下代码涉及 Vue 2.0 及 ES6 语法. 目标 纯 javascrpit 实现,兼容ie9及以上浏览器,在本地做好文件格式.长宽.大小的检测,减少浏览器交互. 现实是残酷的,为了兼容Ie9 还是用上了 flash,第二篇来解释解释. 代码结构 <div id="wrap"> <label> 点我上传图片 <input type='file' @change="change" ref="input"> &

  • cropper js基于vue的图片裁剪上传功能的实现代码

    前些日子做了一个项目关于vue项目需要头像裁剪上传功能,看了一篇文章,在此基础上做的修改完成了这个功能,与大家分享一下.原文:http://www.jb51.net/article/135719.htm 首先下载引入cropper js, npm install cropper js --save 在需要的页面引入:import Cropper from "cropper js" html的代码如下: <template> <div id="demo&quo

  • Vue 图片压缩并上传至服务器功能

    本文主要讲解基于 Vue + Vant ,实现移动端图片选择,并用 Canvas 压缩图片,最后上传至服务器.还会封装一个工具类,方便直接调用. 一.工具类封装 废话不多说先上代码,封装一个 CompressImageUtils 工具类: ** * 图片压缩工具类 * 最大高度和最大宽度都为 500,如果超出大小将等比例缩放. * * 注意可能出现压缩后比原图更大的情况,在调用的地方自己判断大小并决定上传压缩前或压缩后的图到服务器. */ // 将base64转换为blob export fun

  • vue+elementUI实现多文件上传与预览功能实战记录(word/PDF/图片/docx/doc/xlxs/txt)

    目录 需求 实现需求 1.利用on-preview+window.open()实现简易版预览效果 2.封装组件实现更完整的上传完成.预览功能 追加关于问的比较多的问题回复 1.imgsrc路径 2.显示原本elementui的那个上传样式 3.file.response显示没有这个属性和方法 4.https://view.officeapps.live.com/op/view.aspx?src=${data}是干嘛的?预览PDF需要安装其他的插件吗? 总结 需求 最近在做vue2.0+eleme

  • vue中使用axios post上传头像/图片并实时显示到页面的方法

    在前端开发中,为了更好的用户体验,在头像上传时会先将图片显示到页面然后点击保存按钮 完成图片的上传成功 代码部分有参考他人的写法. html代码: <div id="myPhoto" v-show="personalPhoto"> <div class="viewPhoto"> <img src="" alt="" id="portrait"style=&q

  • vue中实现图片和文件上传的示例代码

    html页面 <input type="file" value="" id="file" @change='onUpload'>//注意不能带括号 js代码 methods: { //上传图片 onUpload(e){ var formData = new FormData(); f ormData.append('file', e.target.files[0]); formData.append('type', 'test');

随机推荐