import React , { useRef , useImperativeHandle , forwardRef } from 'react' ; import ReactCropper , { ReactCropperProps } from 'react-cropper' ; import lrz from 'lrz' ; import 'cropperjs/dist/cropper.css' ; interface LrzResult { base64 : string ; base64Len : number ; file : Blob ; fileLen : number ; formData : FormData ; origin : string ; } function Cropper ( { src } , ref ) { const cropper = useRef < any > ( ) ; useImperativeHandle ( ref , ( ) => ( { submit } ) ) ; function submit ( type = 'file' ) { return new Promise ( ( resolve , reject ) => { const croppedURL = cropper . current . getCroppedCanvas ( ) . toDataURL ( ) ; if ( typeof croppedURL === 'undefined' ) { reject ( '未成功获取截图' ) ; } lrz ( croppedURL , { quality : 0.7 } ) . then ( ( res ) => { if ( type === 'dataurl' ) { resolve ( res ) ; } const blob = dataURLToBlob ( res . base64 ) ; if ( type === 'blob' ) { resolve ( blob ) ; } const file = new File ( [ blob ] , 'avatar.jpg' , { type : 'image/jpeg' } ) ; resolve ( file ) ; } ) ; } ) ; } function dataURLToBlob ( base64 ) { const block = base64 . split ( ';' ) ; const contentType = block [ 0 ] . split ( ':' ) [ 1 ] ; const b64Data = block [ 1 ] . split ( ',' ) [ 1 ] ; const sliceSize = 512 ; const byteCharacters = atob ( b64Data ) ; const byteArrays = [ ] ; for ( let offset = 0 ; offset < byteCharacters . length ; offset += sliceSize ) { const slice = byteCharacters . slice ( offset , offset + sliceSize ) ; const byteNumbers = new Array ( slice . length ) ; for ( let i = 0 ; i < slice . length ; i ++ ) { byteNumbers [ i ] = slice . charCodeAt ( i ) ; } const byteArray = new Uint8Array ( byteNumbers ) ; byteArrays . push ( byteArray ) ; } const blob = new Blob ( byteArrays , { type : contentType } ) ; return blob ; } return ( < ReactCropper ref = { cropper as any } src = { src } viewMode = { 1 } zoomable = { true } aspectRatio = { 1 } guides = { true } / > ) ; } export default forwardRef ( Cropper ) ;