1.PC端截图插件的使用
主流的插件都有三种:Cropper.js 、 vue-cropper vue-cropper 、 vue-img-cutter
vue-cropper官网
本人使用的vue-cropper案例
https://blog.csdn.net/qq_41107231/article/details/109725839
https://juejin.cn/post/7189548709456773179
https://juejin.cn/post/7200625292855967805
https://juejin.cn/post/7032295846658097159
https://blog.csdn.net/weixin_46115860/article/details/107430614(详细)
- 安装
# npm 安装
npm install vue-cropper
- 引入
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
- 代码中使用
<vueCropper
ref="cropper"
:img="option.img"
:outputSize="option.size"
:outputType="option.outputType"
></vueCropper>
- 文档配置信息
| 名称 | 功能 | 默认值 | 可选值 | |
|---|---|---|---|---|
| img | 裁剪图片的地址 | 空 | url 地址, base64, blob | |
| outputSize | 裁剪生成图片的质量 | 1 | 0.1 ~ 1 | |
| outputType | 裁剪生成图片的格式 | jpg (jpg 需要传入jpeg) | jpeg, png, webp | |
| info | 裁剪框的大小信息 | true | true, false | |
| canScale | 图片是否允许滚轮缩放 | true | true, false | |
| autoCrop | 是否默认生成截图框 | false | true, false | |
| autoCropWidth | 默认生成截图框宽度 | 容器的 80% | 0 ~ max | |
| autoCropHeight | 默认生成截图框高度 | 容器的 80% | 0 ~ max | |
| fixed | 是否开启截图框宽高固定比例 | false | true, false | |
| fixedNumber | 截图框的宽高比例 | [1, 1] | [ 宽度 , 高度 ] | |
| full | 是否输出原图比例的截图 | false | true, false | |
| fixedBox | 固定截图框大小 | 不允许改变 | false | true, false |
| canMove | 上传图片是否可以移动 | true | true, false | |
| canMoveBox | 截图框能否拖动 | true | true, false | |
| original | 上传图片按照原始比例渲染 | false | true, false | |
| centerBox | 截图框是否被限制在图片里面 | false | true, false | |
| high | 是否按照设备的dpr 输出等比例图片 | true | true, false | |
| infoTrue | true 为展示真实输出图片宽高 false 展示看到的截图框宽高 | false | true, false | |
| maxImgSize | 限制图片最大宽度和高度 | 2000 | 0 ~ max | |
| enlarge | 图片根据截图框输出比例倍数 | 1 | 0 ~ max(建议不要太大不然会卡死的呢) | |
| mode | 图片默认渲染方式 | contain | contain , cover, 100px, 100% auto |
- 内置的方法
通过 this.$refs.cropper 调用
属性
| 属性 | 说明 |
|---|---|
| this.$refs.cropper.cropW | 截图框宽度 |
| this.$refs.cropper.cropH | 截图框高度 |
方法
| 方法 | 说明 |
|---|---|
| this.$refs.cropper.startCrop() | 开始截图 |
| this.$refs.cropper.stopCrop() | 停止截图 |
| this.$refs.cropper.clearCrop() | 清除截图 |
| this.$refs.cropper.changeScale() | 修改图片大小 正数为变大 负数变小 |
| this.$refs.cropper.getImgAxis() | 获取图片基于容器的坐标点 |
| this.$refs.cropper.getCropAxis() | 获取截图框基于容器的坐标点 |
| this.$refs.cropper.goAutoCrop | 自动生成截图框函数 |
| this.$refs.cropper.rotateRight() | 向右边旋转90度 |
| this.$refs.cropper.rotateLeft() | 向左边旋转90度 |
- 自己的案例效果
功能描述:
1)、放大、缩小、旋转、重置
2)、等比例放大缩小
3)、可以一打开固定宽高
4)、裁剪的背景可以更换,重点需要注意的是采用jpeg || png || webp
5)、等等很全,里面的配置都有,有的设置false
- 在对话框el-dialog内使用的
<template>
<el-dialog
width="50%"
title="截图"
v-if="dialogVisible2"
:visible.sync="dialogVisible2"
:before-close="handleClose2"
class="innerDialog"
:modal ="false"
show-close
>
<!-- v-el-drag-dialog
:modal="false"
:close-on-click-modal="false"
-->
<div class="innerDiv">
<!-- <CropperPage/> -->
<div id="VueCropper">
<div class="cropper-content">
<div class="cropper-box">
<div class="cropper">
<vue-cropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:canScale="option.canScale"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:full="option.full"
:fixedBox="option.fixedBox"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:centerBox="option.centerBox"
:height="option.height"
:infoTrue="option.infoTrue"
:maxImgSize="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@imgLoad="imgLoad"
>
</vue-cropper>
</div>
<!--底部操作工具按钮-->
<div class="footer-btn">
<div class="scope-btn">
<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="primary" @click="reset()"
>重置
<!-- <i class="el-icon-upload"></i> -->
</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 class="upload-btn">
<el-button size="mini" @click="cancel()"
>取消
<!-- <i class="el-icon-upload"></i> -->
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
</el-dialog>
<script>
import { defineComponent } from "vue";
import { VueCropper } from "vue-cropper";
import store from "@/store/store.js";
// import elDragDialog from "@/utils/cropperIndex.js"; //引入拖动的自定义指令
// import from
export default {
name: "CropperPage",
// directives: {
// elDragDialog
// },
data() {
return {
previews: {},
option: {
img: "", //裁剪图片的地址
outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
outputType: "jpeg", //裁剪生成图片的格式(jpeg || png || webp)
info: false, //图片大小信息
canScale: true, //图片是否允许滚轮缩放
autoCrop: true, //是否默认生成截图框
autoCropWidth: 687, //默认生成截图框宽度
autoCropHeight: 550, //默认生成截图框高度
fixed: true, //是否开启截图框宽高固定比例
fixedNumber: [5, 4], //截图框的宽高比例
full: true, //false按原比例裁切图片,不失真
fixedBox: false, //固定截图框大小,不允许改变
canMove: true, //上传图片是否可以移动
canMoveBox: true, //截图框能否拖动
original: false, //上传图片按照原始比例渲染
centerBox: false, //截图框是否被限制在图片里面
height: true, //是否按照设备的dpr 输出等比例图片
infoTrue: false, //true为展示真实输出图片宽高,false展示看到的截图框宽高
maxImgSize: 3000, //限制图片最大宽度和高度
enlarge: 1, //图片根据截图框输出比例倍数
mode: "contain" //图片默认渲染方式
},
productDialogVisible2: false,
companyDialogVisible2: false,
statusDialogVisible2: false
};
},
computed: {
dialogVisible2: {
get() {
return store.state.editDialog;
},
set(val) {}
}
},
components: {
VueCropper
},
methods: {
handleClose2(e) {
store.commit("changeeditDialog", false);
store.commit("changeMask", 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();
},
//选择图片
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
let 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.option.img = data;
};
//转化为base64
reader.readAsDataURL(file);
},
//上传图片
uploadImg(type) {
// console.log("type",type);
let _this = this;
this.$refs.cropper.getCropBlob(async data => {
let formData = new FormData();
formData.append("file", data, "DX.jpg");
//调用axios上传 let {data: res} =
await _this.$http
.post(
"http://api.700e.com/admin/common/putDestockingPublicFile",
formData
)
.then(res => {
// console.log("截图上传res", res);
if (res.status === "success") {
let imgPath = res.data.domain + res.data.path;
if(store.state.category=="product"){
// console.log("11111111111");
this.$emit("imgPathFn", imgPath);
}else{
// console.log("222222222");
this.$emit("imgPathFn2", imgPath);
}
store.commit("changeMask",false)
store.commit("changeeditDialog", false);
// this.ruleForm.productImgsURL.push(imgPath);
// console.log(this.ruleForm);
} else {
this.$message.error("图片上传失败");
}
});
store.commit("changeeditbtn1", false);
store.commit("changeeditbtn2", false);
});
},
reset() {
this.$refs.cropper.reload();
this.$refs.cropper.rotateClear();
},
cancel() {
store.commit("changeeditbtn1", false);
store.commit("changeeditbtn2", false);
store.commit("changeeditDialog", false);
store.commit("changeMask", false);
console.log("正在点击外围");
}
},
created(){
// var modal = document.getElementsByClassName('modal');
},
mounted() {
this.option.img = store.state.editImgUrl;
},
updated() {
this.option.img = store.state.editImgUrl;
},
destroyed(){
// console.log("正在销毁");
this.option.img = ""
store.commit("changeeditImgUrl","")
}
};
</script>
<style lang="less">
#VueCropper {
width: 96%;
height: 100%;
// background-color: pink;
position: absolute;
z-index: 100;
}
.cropper-content {
width: 100%;
height: 86%;
background-color: white;
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.cropper-box {
flex: 1;
width: 100%;
.cropper {
width: auto;
height: 550px;
}
}
.show-preview {
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
.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;
}
}
</style>
// 覆盖层元素增加可穿透点击事件
.el-dialog__wrapper {
pointer-events:none;
}
// 弹窗层元素不可穿透点击事件(不影响弹窗层元素的点击事件)
.el-dialog{
pointer-events:auto;
}
注意:此处的代码是针对自己做的遮罩层,点击返回上级,因为自己的业务需求,插件自身的带的遮罩层会盖住自己的遮罩层,此时就需要这几行css