时间:2021-05-26
本文实例为大家分享了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 看一下页面中的效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文介绍了微信小程序图片选择区域屏裁剪实现方法,分享给大家。具体如下:效果图HTML代码开始裁剪点击上传图片点击确认等屏裁剪区域裁剪重新裁剪CSS代码.imgC
本文主要讲解基于Vue+Vant,实现移动端图片选择,并用Canvas压缩图片,最后上传至服务器。还会封装一个工具类,方便直接调用。一、工具类封装废话不多说先上
vue项目打包后上传至GitHub,并实现github-pages的预览1.打包vue项目vue项目:命令行输入打包命令npmrunbuild,生成了dist文
本文实例为大家分享了JavaWeb实现裁剪图片上传完整案例,供大家参考,具体内容如下实现思路•使用jcrop插件手机要裁剪图片的坐标•将
本文实例讲述了基于.net实现裁剪网站上传图片的方法。由于客户端Javascript不能操作文件,所以只能先上传图片再在服务器端剪切。1、上传图片2、Javas