1.效果
2.使用组件
< Cropper ref = " cropperRef" :imgUrl = " url" @searchImg = " searchImg" > </ Cropper>
3.封装组件
< template>
< el- dialog : title= "title" : visible. sync= "dialogVisible" width= "1000px" >
< input ref= "input" type= "file" name= "image" @change= "setImage" / >
< div class = "flex justify-around" >
< div class = "w-480px h-270px flex justify-center items-center" >
< div
v- show= "!imgSrc"
@click= "showFileChooser"
class = "w-full h-full flex cursor-pointer justify-center items-center border-1px border-dashed border-gray-300 rounded-lg"
>
< i class = "font-size-20px el-icon-plus avatar-uploader-icon" > < / i>
< / div>
< ! -- : aspect- ratio= "16 / 16" -- >
< vue- cropper
v- show= "imgSrc"
class = "w-full h-full"
ref= "cropper"
: src= "imgSrc"
alt= "Source Image"
@ready= "ready"
@cropstart= "cropstart"
@cropmove= "cropmove"
@cropend= "cropend"
@crop= "crop"
@zoom= "zoom"
preview= ".preview"
: autoCropArea= "autoCropArea"
>
< / vue- cropper>
< / div>
< div class = "w-420px" >
< div class = "font-bold color-#666 ml-20px mb-10px" > 预览< / div>
< div v- show= "!imgSrc" class = "preview_empty ml-20px" > < / div>
< div v- show= "imgSrc" class = "preview ml-20px" > < / div>
< ! -- < div> 裁剪图片< / div>
< div class = "cropped-image" >
< el- image class = "h-180px" v- if = "cropImg" : src= "cropImg" alt= "Cropped Image" / >
< div v- else class = "crop-placeholder" / >
< / div> -- >
< div class = "actions mt-10px ml-10px" >
< el- button class = "mb-10px ml-10px" type= "primary" @click= "zoom(0.2)" size= "small" > 放大< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "zoom(-0.2)" size= "small" > 缩小< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "move(-10, 0)" size= "small" > 左移< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "move(10, 0)" size= "small" > 右移< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "move(0, -10)" size= "small" > 上移< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "move(0, 10)" size= "small" > 下移< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "rotate(90)" size= "small" > 旋转90 °< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "rotate(-90)" size= "small" > 旋转- 90 °< / el- button>
< ! -- < el- button class = "mb-10px" type= "primary" @click= "flipX" size= "small" > 水平翻转< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "flipY" size= "small" > 垂直翻转< / el- button> -- >
< ! -- < el- button class = "mb-10px" type= "success" @click= "cropImage" size= "small" > 搜索< / el- button> -- >
< el- button class = "mb-10px" type= "primary" @click= "reset" size= "small" plain> 重置< / el- button>
< el- button
v- if = "!isHideFileChooser"
class = "mb-10px"
type= "success"
@click= "showFileChooser"
size= "small"
plain
> 更换图片< / el- button
>
< ! -- < el- button class = "mb-10px" type= "primary" @click= "getCropBoxData" size= "small" > 获取裁剪框数据< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "setCropBoxData" size= "small" > 设置裁剪框数据< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "getData" size= "small" > 获取裁剪数据< / el- button>
< el- button class = "mb-10px" type= "primary" @click= "setData" size= "small" > 设置裁剪数据< / el- button> -- >
< / div>
< / div>
< / div>
< span slot= "footer" class = "dialog-footer" >
< el- button size= "small" @click= "dialogVisible = false" > 取 消< / el- button>
< el- button size= "small" type= "primary" @click= "cropImage" > 搜索< / el- button>
< / span>
< / el- dialog>
< / template>
< script>
import VueCropper from 'vue-cropperjs'
import 'cropperjs/dist/cropper.css'
export default {
name : 'Cropper' ,
components : { VueCropper } ,
props : {
title : {
type : String,
default : '图片框选'
} ,
imgUrl : {
type : String,
default : ''
} ,
autoCropArea : {
type : Number,
default : 0.6
} ,
isHideFileChooser : {
type : Boolean,
default : true
}
} ,
data ( ) {
return {
imgSrc : '' ,
dialogVisible : false ,
cropImg : ''
}
} ,
watch : {
imgUrl ( val ) {
if ( val) {
this . imgSrc = val
console. log ( '🚀 ~ imgUrl ~ this.imgSrc:' , this . imgSrc)
}
}
} ,
methods : {
open ( ) {
if ( ! this . imgUrl) {
this . imgSrc = ''
}
this . dialogVisible = true
} ,
handleClose ( ) {
this . $emit ( 'close' )
} ,
ready ( ) {
} ,
cropImage ( ) {
this . cropImg = this . $refs. cropper. getCroppedCanvas ( ) . toDataURL ( )
const base64Data = this . cropImg. split ( ',' ) [ 1 ]
this . $emit ( 'searchImg' , base64Data)
this . dialogVisible = false
} ,
cropstart ( ) {
} ,
cropmove ( ) {
} ,
cropend ( ) {
} ,
crop ( data ) {
} ,
flipX ( ) {
const dom = this . $refs. flipX
let scale = dom. getAttribute ( 'data-scale' )
scale = scale ? - scale : - 1
this . $refs. cropper. scaleX ( scale)
dom. setAttribute ( 'data-scale' , scale)
} ,
flipY ( ) {
const dom = this . $refs. flipY
let scale = dom. getAttribute ( 'data-scale' )
scale = scale ? - scale : - 1
this . $refs. cropper. scaleY ( scale)
dom. setAttribute ( 'data-scale' , scale)
} ,
getCropBoxData ( ) {
this . data = JSON . stringify ( this . $refs. cropper. getCropBoxData ( ) , null , 4 )
} ,
getData ( ) {
this . data = JSON . stringify ( this . $refs. cropper. getData ( ) , null , 4 )
console. log ( '🚀 ~ getData ~ this.data:' , this . data)
} ,
move ( offsetX, offsetY ) {
this . $refs. cropper. move ( offsetX, offsetY)
} ,
reset ( ) {
this . $refs. cropper. reset ( )
} ,
rotate ( deg ) {
this . $refs. cropper. rotate ( deg)
} ,
setCropBoxData ( ) {
if ( ! this . data) return
this . $refs. cropper. setCropBoxData ( JSON . parse ( this . data) )
} ,
setData ( ) {
if ( ! this . data) return
this . $refs. cropper. setData ( JSON . parse ( this . data) )
} ,
setImage ( e ) {
const file = e. target. files[ 0 ]
if ( file. type. indexOf ( 'image/' ) === - 1 ) {
alert ( 'Please select an image file' )
return
}
if ( typeof FileReader === 'function' ) {
const reader = new FileReader ( )
reader. onload = ( event ) => {
this . imgSrc = event. target. result
this . $refs. cropper. replace ( event. target. result)
}
reader. readAsDataURL ( file)
} else {
alert ( 'Sorry, FileReader API not supported' )
}
} ,
showFileChooser ( ) {
this . $refs. input. click ( )
} ,
zoom ( percent ) {
this . $refs. cropper. relativeZoom ( percent)
}
} ,
mounted ( ) {
this . imgSrc = this . imgUrl
}
}
< / script>
< style lang= "scss" scoped>
input[ type= 'file' ] {
display : none;
}
. preview- area {
width : 100 % ;
}
. preview- area p {
font- size: 1 . 25rem;
margin : 0 ;
margin- bottom: 1rem;
}
. preview- area p: last- of - type {
margin- top: 1rem;
}
. preview {
width : 270px;
height : calc ( 270px * ( 9 / 16 ) ) ;
overflow : hidden;
background- color: #f5f5f5;
}
. preview_empty {
width : 270px;
height : calc ( 270px * ( 9 / 16 ) ) ;
overflow : hidden;
background- color: #f5f5f5;
}
. crop- placeholder {
width : 100 % ;
height : 200px;
background : #ccc;
}
. cropped- image img {
max- width: 100 % ;
}
< / style>