ADD component sc-cropper
1:增加组件 scCropper 2:scUpload内置scCropper
This commit is contained in:
parent
0908c26d5d
commit
bd4fd271c1
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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: "",
|
||||
|
|
|
|||
Loading…
Reference in New Issue