VueCropper 使用
1. 安装
npm install vue-cropper --save-dev
2. 使用
<template> <div> <el-dialog title="选择图片" :visible.sync="isShowCropper" :before-close="handleClose" width="580px" > <div class="cropper-content"> <div class="cropper-box"> <div class="cropper"> <vue-cropper ref="cropper" :img="options.img" :outputSize="options.outputSize" :outputType="options.outputType" :info="options.info" :canScale="options.canScale" :autoCrop="options.autoCrop" :autoCropWidth="options.autoCropWidth" :autoCropHeight="options.autoCropHeight" :fixed="options.fixed" :fixedNumber="options.fixedNumber" :full="options.full" :fixedBox="options.fixedBox" :canMove="options.canMove" :canMoveBox="options.canMoveBox" :original="options.original" :centerBox="options.centerBox" :height="options.height" :infoTrue="options.infoTrue" :maxImgSize="options.maxImgSize" :enlarge="options.enlarge" :mode="options.mode" @realTime="realTime" @imgLoad="imgLoad" > </vue-cropper> </div> <!--底部操作工具按钮--> <div class="footer-btn"> <div class="scope-btn"> <label class="btn" for="uploads">选择图片</label> <input type="file" id="uploads" style="position: absolute; clip: rect(0 0 0 0)" accept="image/png, image/jpeg, image/gif, image/jpg" @change="selectImg($event)" /> <el-button size="mini" type="danger" plain icon="el-icon-zoom-in" @click="changeScale(1)" >放大</el-button > <el-button size="mini" type="danger" plain icon="el-icon-zoom-out" @click="changeScale(-1)" >缩小</el-button > <el-button size="mini" type="danger" plain @click="rotateLeft" >↺ 左旋转</el-button > <el-button size="mini" type="danger" plain @click="rotateRight" >↻ 右旋转</el-button > </div> <div class="upload-btn"> <el-button size="mini" type="success" @click="uploadImg('blob')" >上传图片 <i class="el-icon-upload"></i ></el-button> </div> </div> </div> <!--预览效果图--> <!-- <div class="show-preview"> <div :style="previews.div" class="preview"> <img :src="previews.url" :style="previews.img" /> </div> </div> --> </div> </el-dialog> <div class="cropper-upload" @click="handlerOpenCropper"> <img class="cropper-upload-avatar" v-if="imageUrl" :src="imageUrl | imgUrl" /> <i v-else class="el-icon-plus cropper-upload-icon"></i> </div> </div> </template> <script> import { VueCropper } from "vue-cropper"; import { upload } from "@/api/api"; export default { name: "CropperImage", components: { VueCropper }, props: { imageUrl: { type: String, default: "" }, options: { type: Object, default: () => {} }, imageParams: { type: String, default: "" }, fileIndex: { type: Number, default: -1 } }, mounted() { this.options.img = ""; }, data() { return { isShowCropper: false, previews: {} }; }, methods: { // 打开上传图片弹框 handlerOpenCropper() { if (!this.disabled) { this.options.img = ""; this.isShowCropper = true; } }, // 关闭弹框 handleClose() { this.isShowCropper = false; }, //初始化函数 imgLoad(msg) { // console.log("工具初始化函数=====" + msg); }, //图片缩放 changeScale(num) { num = num || 1; this.$refs.cropper.changeScale(num); }, //向左旋转 rotateLeft() { this.$refs.cropper.rotateLeft(); }, //向右旋转 rotateRight() { this.$refs.cropper.rotateRight(); }, //实时预览函数 realTime(data) { this.previews = data; }, //选择图片 selectImg(e) { let file = e.target.files[0]; if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) { this.$message({ message: "图片类型要求:jpeg、jpg、png", type: "error" }); return false; } //转化为blob 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.options.img = data; }; //转化为base64 reader.readAsDataURL(file); }, //上传图片 uploadImg(type) { let _this = this; if (type === "blob") { //获取截图的blob数据 this.$refs.cropper.getCropBlob(async data => { let formData = new FormData(); var fileOfBlob = new File([data], new Date().getTime() + "_pic.png"); formData.append("file", fileOfBlob); const sizeFlag = data.size / 1024 / 1024 < 2; if (!sizeFlag) { this.$message.error("上传文件大小不能超过 2MB!"); } //调用axios上传 let res = await upload(formData); if (res.code === 0) { _this.$message({ message: "上传成功!", type: "success" });
// 注意参数imageParams if (this.imageParams != "") { _this.$emit("cropperChangeImages", { imageUrl: res.filePath, imageParams: _this.imageParams, fileIndex: _this.fileIndex }); } else { _this.$emit("cropperChangeImages", res.filePath); } var change = document.getElementById("uploads"); this.clearInputFile(change); _this.handleClose(); } else { _this.$message({ message: res.msg, type: "error" }); _this.handleClose(); } }); } else { this.$refs.cropper.getCropData(async data => { _this.handleClose(); }); } }, clearInputFile(f) { if (f.value) { try { f.value = ""; //for IE11, latest Chrome/Firefox/Opera... } catch (err) {} if (f.value) { //for IE5 ~ IE10 var form = document.createElement("form"), ref = f.nextSibling, p = f.parentNode; form.appendChild(f); form.reset(); p.insertBefore(f, ref); } } } } }; </script> <style scoped lang="scss"> .cropper-content { // display: flex; // display: -webkit-flex; // justify-content: flex-end; width: 530px; margin: 0 auto; .cropper-box { // flex: 1; // width: 100%; .cropper { width: auto; height: 300px; } } .show-preview { flex: 1; -webkit-flex: 1; display: flex; display: -webkit-flex; justify-content: center; display: none; .preview { overflow: hidden; border: 1px solid #67c23a; background: #cccccc; } } } .footer-btn { margin-top: 30px; display: flex; display: -webkit-flex; justify-content: flex-end; .scope-btn { display: flex; display: -webkit-flex; justify-content: space-between; padding-right: 10px; } .upload-btn { flex: 1; -webkit-flex: 1; display: flex; display: -webkit-flex; justify-content: center; } .btn { outline: none; display: inline-block; line-height: 1; white-space: nowrap; cursor: pointer; -webkit-appearance: none; text-align: center; -webkit-box-sizing: border-box; box-sizing: border-box; outline: 0; -webkit-transition: 0.1s; transition: 0.1s; font-weight: 500; padding: 8px 15px; font-size: 12px; border-radius: 3px; color: #fff; background-color: #409eff; border-color: #409eff; margin-right: 10px; } } // 图片样式 .cropper-upload { width: 200px; height: 200px; border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; &:hover { border-color: $theme; } .cropper-upload-icon { font-size: 40px; color: #8c939d; width: 200px; height: 200px; line-height: 200px; text-align: center; } .cropper-upload-avatar { width: 200px; height: 200px; display: block; } } </style>
3.
import CropperImage from "@/components/Common/CropperImage";
<CropperImage :imageUrl="ruleForm.photo" :options="options" @cropperChangeImages="cropperChangeImages" ></CropperImage> options: { img: "", //裁剪图片的地址 outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1) outputType: "png", //裁剪生成图片的格式(jpeg || png || webp) info: true, //图片大小信息 canScale: true, //图片是否允许滚轮缩放 autoCrop: true, //是否默认生成截图框 autoCropWidth: 200, //默认生成截图框宽度 autoCropHeight: 200, //默认生成截图框高度 fixed: true, //是否开启截图框宽高固定比例 fixedNumber: [1, 1], //截图框的宽高比例 full: false, //false按原比例裁切图片,不失真 fixedBox: true, //固定截图框大小,不允许改变 canMove: false, //上传图片是否可以移动 canMoveBox: true, //截图框能否拖动 original: false, //上传图片按照原始比例渲染 centerBox: false, //截图框是否被限制在图片里面 height: true, //是否按照设备的dpr 输出等比例图片 infoTrue: false, //true为展示真实输出图片宽高,false展示看到的截图框宽高 maxImgSize: 3000, //限制图片最大宽度和高度 enlarge: 1, //图片根据截图框输出比例倍数 mode: "200px 200px" //图片默认渲染方式 }, // 上传图片成功返回值(正面) cropperChangeImages(url) { this.ruleForm.photo = url; },