ADD component sc-cropper

1:增加组件 scCropper
2:scUpload内置scCropper
This commit is contained in:
sakuya 2021-07-24 22:32:41 +08:00
parent 0908c26d5d
commit bd4fd271c1
5 changed files with 233 additions and 7 deletions

View File

@ -11,6 +11,7 @@
"@tinymce/tinymce-vue": "4.0.3",
"axios": "0.21.1",
"core-js": "3.15.2",
"cropperjs": "^1.5.12",
"crypto-js": "4.0.0",
"echarts": "5.1.2",
"element-plus": "1.0.2-beta.54",
@ -27,11 +28,11 @@
"@vue/cli-plugin-eslint": "4.5.13",
"@vue/cli-service": "4.5.13",
"@vue/compiler-sfc": "3.1.4",
"less": "3.13.1",
"less-loader": "7.3.0",
"babel-eslint": "10.1.0",
"eslint": "6.8.0",
"eslint-plugin-vue": "7.12.1"
"eslint-plugin-vue": "7.12.1",
"less": "3.13.1",
"less-loader": "7.3.0"
},
"eslintConfig": {
"root": true,

View File

@ -0,0 +1,83 @@
<!--
* @Descripttion: 图像裁剪组件
* @version: 1.0
* @Author: sakuya
* @Date: 2021年7月24日17:05:43
* @LastEditors:
* @LastEditTime:
* @other: 代码完全开源欢迎参考也欢迎PR
-->
<template>
<div class="sc-cropper">
<div class="sc-cropper__img">
<img :src="src" ref="img">
</div>
<div class="sc-cropper__preview">
<h4>图像预览</h4>
<div class="sc-cropper__preview__img" ref="preview"></div>
</div>
</div>
</template>
<script>
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
export default {
props: {
src: { type: String, default: "" },
compress: {type: Number, default: 1},
aspectRatio: {type: Number, default: NaN},
},
data() {
return {
crop: null
}
},
watch:{
aspectRatio(val){
this.crop.setAspectRatio(val)
}
},
mounted() {
this.init()
},
methods: {
init(){
this.crop = new Cropper(this.$refs.img, {
viewMode: 2,
dragMode: 'move',
aspectRatio: this.aspectRatio,
preview: this.$refs.preview
})
},
setAspectRatio(aspectRatio){
this.crop.setAspectRatio(aspectRatio)
},
getCropData(cb, type='image/jpeg'){
cb(this.crop.getCroppedCanvas().toDataURL(type, this.compress))
},
getCropBlob(cb, type='image/jpeg'){
this.crop.getCroppedCanvas().toBlob((blob) => {
cb(blob)
}, type, this.compress)
},
getCropFile(cb, fileName='fileName.jpg', type='image/jpeg'){
this.crop.getCroppedCanvas().toBlob((blob) => {
let file = new File([blob], fileName, {type: type})
cb(file)
}, type, this.compress)
}
}
}
</script>
<style scoped>
.sc-cropper {height:300px;}
.sc-cropper__img {height:100%;width:400px;float: left;background: #EBEEF5;}
.sc-cropper__img img {display: none;}
.sc-cropper__preview {width: 120px;margin-left: 20px;float: left;}
.sc-cropper__preview h4 {font-weight: normal;font-size: 12px;color: #999;margin-bottom: 20px;}
.sc-cropper__preview__img {overflow: hidden;width: 120px;height: 120px;border: 1px solid #ebeef5;}
</style>

View File

@ -8,7 +8,7 @@
<a v-else :href="img" class="file" target="_blank"><i class="el-icon-document"></i></a>
</div>
<div v-else class="sc-upload-uploader">
<el-upload ref="upload" class="uploader" :accept="accept" :action="action" :show-file-list="false" :before-upload="before" :on-success="success" :on-error="error" :http-request="request">
<el-upload ref="upload" class="uploader" :auto-upload="!cropper" :on-change="change" :accept="accept" :action="action" :show-file-list="false" :before-upload="before" :on-success="success" :on-error="error" :http-request="request">
<slot>
<div class="file-empty">
<i :class="icon"></i>
@ -17,12 +17,21 @@
</slot>
</el-upload>
</div>
<el-dialog title="剪裁" v-model="cropperDialogVisible" :width="580" destroy-on-close>
<sc-cropper :src="cropperImg" :compress="compress" :aspectRatio="aspectRatio" ref="cropper"></sc-cropper>
<template #footer>
<el-button @click="cropperDialogVisible=false" > </el-button>
<el-button type="primary" @click="cropperSave"> </el-button>
</template>
</el-dialog>
<el-input v-model="img" style="display:none"></el-input>
</div>
</template>
<script>
import config from "@/config/upload";
import config from "@/config/upload"
import scCropper from '@/components/scCropper';
export default {
props: {
@ -35,8 +44,14 @@
maxSize: { type: Number, default: config.maxSize },
title: { type: String, default: "" },
icon: { type: String, default: "el-icon-plus" },
cropper: { type: Boolean, default: false },
compress: {type: Number, default: 1},
aspectRatio: {type: Number, default: NaN},
onSuccess: { type: Function, default: () => { return true } }
},
components: {
scCropper
},
data() {
return {
loading: false,
@ -46,7 +61,10 @@
style: {
width: this.width + "px",
height: this.height + "px"
}
},
cropperDialogVisible: false,
cropperImg: "",
cropperUploadFile: null
}
},
watch:{
@ -63,6 +81,14 @@
this.img = this.modelValue;
},
methods: {
cropperSave(){
var uploadFile = this.$refs.upload.uploadFiles[0].raw
this.$refs.cropper.getCropFile(file => {
this.cropperUploadFile = file
this.$refs.upload.submit()
}, uploadFile.name, uploadFile.type)
this.cropperDialogVisible = false
},
isImg(fileUrl){
var strRegex = "(.jpg|.png|.gif|.jpeg)$";
var re = new RegExp(strRegex);
@ -72,7 +98,22 @@
this.fileIsImg=false;
}
},
change(file){
if(this.cropper && file.status=='ready'){
this.isImg(file.name)
if(!this.fileIsImg){
this.$notify.warning({
title: '上传文件警告',
message: '选择的文件非图像类文件'
})
return false
}
this.cropperDialogVisible = true
this.cropperImg = URL.createObjectURL(file.raw)
}
},
before(file){
file = this.cropper ? this.cropperUploadFile : file
const maxSize = file.size / 1024 / 1024 < this.maxSize;
if (!maxSize) {
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`);
@ -114,7 +155,8 @@
apiObj = this.apiObj;
}
const data = new FormData();
data.append("file", param.file);
var file = this.cropper ? this.cropperUploadFile : param.file
data.append("file", file);
apiObj.post(data).then(res => {
param.onSuccess(res)
}).catch(err => {

98
src/views/vab/cropper.vue Normal file
View File

@ -0,0 +1,98 @@
<!--
* @Descripttion: 图像剪裁组件演示文件
* @version: 1.0
* @Author: sakuya
* @Date: 2021年7月24日20:58:51
* @LastEditors:
* @LastEditTime:
-->
<template>
<el-main>
<el-row :gutter="15">
<el-col :lg="14">
<el-card shadow="never">
<sc-cropper :src="cropperImg" :compress="compress" :aspectRatio="aspectRatio" ref="cropper"></sc-cropper>
</el-card>
<el-card shadow="never" header="参数和方法">
<el-form label-width="100px">
<el-form-item label="aspectRatio">
<el-select v-model="aspectRatio" placeholder="请选择">
<el-option label="自由" :value="0"></el-option>
<el-option label="1:1" :value="1/1"></el-option>
<el-option label="4:3" :value="4/3"></el-option>
<el-option label="16:9" :value="16/9"></el-option>
</el-select>
<div class="el-form-item-msg">固定选区或者不固定</div>
</el-form-item>
<el-form-item label="compress">
<el-select v-model="compress" placeholder="请选择">
<el-option label="0.1" :value="0.1"></el-option>
<el-option label="0.5" :value="0.5"></el-option>
<el-option label="1" :value="1"></el-option>
</el-select>
<div class="el-form-item-msg">图像压缩率值为0.1-1</div>
</el-form-item>
</el-form>
<el-button type="primary" plain @click="getBase64">Base64</el-button>
<el-button type="primary" plain @click="getBlob">Blob</el-button>
<el-button type="primary" plain @click="getFile">File</el-button>
</el-card>
<el-card shadow="never" header="方法结果">
<img :src="imgData" />
</el-card>
</el-col>
<el-col :lg="10">
<el-card shadow="never" header="已内置剪裁的上传组件">
<el-alert title="设置cropper就可以开启上传前剪裁, 并已封装compress和aspectRatio, 打开F12查看网络请求" type="success" style="margin-bottom:20px;"></el-alert>
<sc-upload v-model="uploadImg" title="开启剪裁" :cropper="true" :compress="1" :aspectRatio="1/1"></sc-upload>
</el-card>
</el-col>
</el-row>
</el-main>
</template>
<script>
import scCropper from '@/components/scCropper'
export default {
name: 'cropper',
components: {
scCropper
},
data() {
return {
cropperImg: 'img/avatar.jpg',
compress: 0.5,
aspectRatio: 0,
uploadImg: '',
imgData: ''
}
},
methods: {
getBase64(){
this.$refs.cropper.getCropData(data=>{
this.imgData = data
})
},
getBlob(){
this.$refs.cropper.getCropBlob(blob=>{
this.imgData = URL.createObjectURL(blob)
})
},
getFile(){
this.$refs.cropper.getCropFile(file=>{
let aTag = document.createElement('a')
aTag.download = file.name;
aTag.href = URL.createObjectURL(file)
aTag.click()
}, 'fileName.jpg', 'image/jpeg')
}
}
}
</script>
<style>
</style>

View File

@ -10,6 +10,7 @@
<p>自定义插槽</p>
</div>
</sc-upload>
<sc-upload v-model="imgurl4" title="开启剪裁" :cropper="true" :compress="1" :aspectRatio="1/1"></sc-upload>
</el-card>
<el-card shadow="never" header="在验证表单中使用">
@ -51,6 +52,7 @@
imgurl: "img/avatar.jpg",
imgurl2: "",
imgurl3: "",
imgurl4: "",
form: {
img1: "",
img2: "",