|
|
@@ -0,0 +1,297 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ title="图片剪裁"
|
|
|
+ :visible="dialogVisible"
|
|
|
+ class="crop-dialog"
|
|
|
+ append-to-body
|
|
|
+ @close="close()"
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <div class="cropper-content">
|
|
|
+ <!-- -->
|
|
|
+ <!-- 剪裁框 -->
|
|
|
+ <div
|
|
|
+ class="cropper"
|
|
|
+ :style="{
|
|
|
+ width: option.autoCropWidth + 'px',
|
|
|
+ height: option.autoCropHeight + 'px',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <VueCropper
|
|
|
+ ref="cropper"
|
|
|
+ :img="option.img"
|
|
|
+ :outputSize="option.size"
|
|
|
+ :outputType="option.outputType"
|
|
|
+ :info="true"
|
|
|
+ :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"
|
|
|
+ :fixed="option.fixed"
|
|
|
+ listType="picture-card"
|
|
|
+ :fixedNumber="fixedNumber"
|
|
|
+ ></VueCropper>
|
|
|
+ </div>
|
|
|
+ <!-- 预览框 -->
|
|
|
+ <div
|
|
|
+ class="show-preview"
|
|
|
+ :style="{
|
|
|
+ width: '50%',
|
|
|
+ height: '428px',
|
|
|
+ overflow: 'hidden',
|
|
|
+ margin: '0 25px',
|
|
|
+ display: 'flex',
|
|
|
+ 'align-items': 'center',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <div :style="previews.div" class="preview">
|
|
|
+ <img :src="previews.url" :style="previews.img" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="footer-btn">
|
|
|
+ <!-- 缩放旋转按钮 -->
|
|
|
+ <div class="scope-btn">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ icon="el-icon-zoom-in"
|
|
|
+ @click="changeScale(1)"
|
|
|
+ ></el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ icon="el-icon-zoom-out"
|
|
|
+ @click="changeScale(-1)"
|
|
|
+ ></el-button>
|
|
|
+ <el-button type="primary" @click="rotateLeft">逆时针旋转</el-button>
|
|
|
+ <el-button type="primary" @click="rotateRight">顺时针旋转</el-button>
|
|
|
+ </div>
|
|
|
+ <!-- 确认上传按钮 -->
|
|
|
+ <div class="upload-btn">
|
|
|
+ <el-button type="primary" @click="uploadImg('blob')">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ previews: {}, // 预览数据
|
|
|
+ option: {
|
|
|
+ img: "", // 裁剪图片的地址 (默认:空)
|
|
|
+ size: 1, // 裁剪生成图片的质量 (默认:1)
|
|
|
+ full: true, // 是否输出原图比例的截图 选true生成的图片会非常大 (默认:false)
|
|
|
+ outputType: "png", // 裁剪生成图片的格式 (默认:jpg)
|
|
|
+ canMove: true, // 上传图片是否可以移动 (默认:true)
|
|
|
+ original: true, // 上传图片按照原始比例渲染 (默认:false)
|
|
|
+ canMoveBox: true, // 截图框能否拖动 (默认:true)
|
|
|
+ autoCrop: true, // 是否默认生成截图框 (默认:false)
|
|
|
+ autoCropWidth: 316, // 默认生成截图框宽度 (默认:80%)
|
|
|
+ autoCropHeight: 428, // 默认生成截图框高度 (默认:80%)
|
|
|
+ fixedBox: false, // 固定截图框大小 不允许改变 (默认:false)
|
|
|
+ fixed: false, // 是否开启截图框宽高固定比例 (默认:true)
|
|
|
+ fixedNumber: [1, 1], // 截图框比例 (默认:[1:1])
|
|
|
+ },
|
|
|
+ data: "",
|
|
|
+ downImg: "#",
|
|
|
+ };
|
|
|
+ },
|
|
|
+ props: ["imgFile", "fixedNumber", "dialogVisible", "w", "h"],
|
|
|
+ mounted() {},
|
|
|
+ methods: {
|
|
|
+ init() {
|
|
|
+ if (this.w && this.h) {
|
|
|
+ if (this.w > this.h) {
|
|
|
+ this.option.autoCropHeight =
|
|
|
+ this.option.autoCropWidth * ((1 / this.w) * this.h);
|
|
|
+ } else {
|
|
|
+ this.option.autoCropWidth =
|
|
|
+ this.option.autoCropWidth * ((1 / this.h) * this.w);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ this.option.autoCropHeight = this.option.autoCropHeight =428;
|
|
|
+ }
|
|
|
+ this.$nextTick(() => {
|
|
|
+ var reader = new FileReader();
|
|
|
+ reader.onload = (e) => {
|
|
|
+ let data;
|
|
|
+ if (typeof e.target.result === "object") {
|
|
|
+ data = window.URL.createObjectURL(new Blob([e.target.result]));
|
|
|
+ } else {
|
|
|
+ data = e.target.result;
|
|
|
+ this.data = data;
|
|
|
+ }
|
|
|
+ this.option.img = data;
|
|
|
+ };
|
|
|
+ // 转化为base64
|
|
|
+ // reader.readAsDataURL(this.imgFile)
|
|
|
+ // 转化为blob
|
|
|
+ reader.readAsArrayBuffer(this.imgFile);
|
|
|
+ setTimeout(() => {
|
|
|
+ let autoCropWidth = this.option.autoCropWidth;
|
|
|
+ let autoCropHeight = this.option.autoCropHeight;
|
|
|
+ this.getImgWidthHeight(this.imgFile, (data) => {
|
|
|
+ if (data.width > autoCropWidth && data.height < autoCropHeight) {
|
|
|
+ let sfbl = autoCropHeight / data.height;
|
|
|
+ this.toChangeScale(sfbl);
|
|
|
+ } else if (data.width < autoCropWidth && data.height > autoCropHeight) {
|
|
|
+ let sfbl = autoCropWidth / data.width;
|
|
|
+ this.toChangeScale(sfbl);
|
|
|
+ } else if (data.width < autoCropWidth && data.height < autoCropHeight) {
|
|
|
+ let sfbl = 1;
|
|
|
+ if (data.width < data.height) sfbl = autoCropWidth / data.width;
|
|
|
+ else sfbl = autoCropHeight / data.height;
|
|
|
+ this.toChangeScale(sfbl);
|
|
|
+ } else {
|
|
|
+ let sfbl = 1;
|
|
|
+ if (data.width < data.height) sfbl = autoCropWidth / data.width;
|
|
|
+ else sfbl = autoCropHeight / data.height;
|
|
|
+ this.toChangeScale(sfbl);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }, 800);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ toChangeScale(sfbl) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.getImgWidthHeight(this.imgFile, (data) => {});
|
|
|
+ this.$refs.cropper.scale = sfbl;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getImgWidthHeight(file, callback) {
|
|
|
+ var reader = new FileReader();
|
|
|
+ reader.onload = function (event) {
|
|
|
+ var base64 = event.target.result;
|
|
|
+ var img = document.createElement("img");
|
|
|
+ img.src = base64;
|
|
|
+ img.onload = function () {
|
|
|
+ callback && callback({ width: img.width, height: img.height });
|
|
|
+ };
|
|
|
+ };
|
|
|
+ reader.readAsDataURL(file);
|
|
|
+ },
|
|
|
+ changeScale(num) {
|
|
|
+ this.getImgWidthHeight(this.imgFile, (data) => {
|
|
|
+ console.log(data);
|
|
|
+ console.log(num);
|
|
|
+ });
|
|
|
+ // 图片缩放
|
|
|
+ num = num || 1;
|
|
|
+ console.log(num);
|
|
|
+ this.$refs.cropper.changeScale(num);
|
|
|
+ },
|
|
|
+ rotateLeft() {
|
|
|
+ // 向左旋转
|
|
|
+ this.$refs.cropper.rotateLeft();
|
|
|
+ },
|
|
|
+ rotateRight() {
|
|
|
+ // 向右旋转
|
|
|
+ this.$refs.cropper.rotateRight();
|
|
|
+ },
|
|
|
+ realTime(data) {
|
|
|
+ // 实时预览
|
|
|
+ this.previews = data;
|
|
|
+ },
|
|
|
+ close() {
|
|
|
+ this.$emit("upload", "close");
|
|
|
+ },
|
|
|
+ uploadImg(type) {
|
|
|
+ // 将剪裁好的图片回传给父组件
|
|
|
+ event.preventDefault();
|
|
|
+ let that = this;
|
|
|
+ if (type === "blob") {
|
|
|
+ this.$refs.cropper.getCropBlob((data) => {
|
|
|
+ let formData = new FormData();
|
|
|
+
|
|
|
+ formData.append("file", data, that.imgFile.name);
|
|
|
+ that.$emit("upload", formData);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$refs.cropper.getCropData((data) => {
|
|
|
+ that.$emit("upload", formData);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style>
|
|
|
+.cropper-content {
|
|
|
+ display: flex;
|
|
|
+ display: -webkit-flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ -webkit-justify-content: flex-end;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+.cropper-content .cropper {
|
|
|
+ width: 50%;
|
|
|
+ height: 428px;
|
|
|
+}
|
|
|
+.cropper-content .show-preview {
|
|
|
+ width: 50%;
|
|
|
+ height: 428px;
|
|
|
+ display: flex;
|
|
|
+ display: -webkit-flex;
|
|
|
+ justify-content: center;
|
|
|
+ -webkit-justify-content: center;
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid #cccccc;
|
|
|
+ /* background: #cccccc; */
|
|
|
+ margin-left: 40px;
|
|
|
+}
|
|
|
+.preview {
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid #e9ebef;
|
|
|
+ background: #e9ebef;
|
|
|
+}
|
|
|
+.footer-btn {
|
|
|
+ margin-top: 30px;
|
|
|
+ display: flex;
|
|
|
+ display: -webkit-flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ -webkit-justify-content: flex-end;
|
|
|
+}
|
|
|
+.footer-btn .scope-btn {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ display: -webkit-flex;
|
|
|
+}
|
|
|
+.footer-btn .upload-btn {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ display: -webkit-flex;
|
|
|
+ justify-content: center;
|
|
|
+ -webkit-justify-content: center;
|
|
|
+ padding: 0 14px;
|
|
|
+}
|
|
|
+.footer-btn .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;
|
|
|
+ margin: 0;
|
|
|
+ -webkit-transition: 0.1s;
|
|
|
+ transition: 0.1s;
|
|
|
+ font-weight: 500;
|
|
|
+ padding: 8px 15px;
|
|
|
+ font-size: 12px;
|
|
|
+ border-radius: 3px;
|
|
|
+ color: #fff;
|
|
|
+ background-color: #67c23a;
|
|
|
+ border-color: #67c23a;
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|