1.摸鱼大法第一招–Cropper
Cropper 就是基于canvas做的小插件,下面做的是一个图片裁剪,各位看官看看就行,有什么意见多提。
// A code block
import Cropper from 'cropperjs';
import 'cropper/dist/cropper.css'
import {useEffect, useState} from 'react';
import './tailor.css'
// import img1 from './images/fredrik-solli-wandem-EXBWaUeR4-g-unsplash.jpg';
/**
* imgUrl: 当前选择的图片,
* onReady: 剪切好后的回调函数
* **/
const Tailor = function (props) {
const { imgfile = '', onReady= () => {} } = props;
//当前图片
const [ tailPic, setTailPic ] = useState();
//当前的Cropper
const [ cropper, setCropper ] = useState();
//当前的旋转角度
const [ rotate, setRotate ] = useState('0');
//是否开启预览
const [ isPreview, setIsPreview ] = useState(false);
useEffect(()=>{
if( !imgfile ) return false;
typeof imgfile === 'string' ? setTailPic(imgfile) : setTailPic( URL.createObjectURL(imgfile) )
},[]);
useEffect(() => {
if( !tailPic ) return false;
const img = document.getElementById('tailor_image');
cropper?.destroy();
img.src = tailPic;
let option = {
aspectRatio: 16 / 9,
viewMode:1,
dragMode: 'move', // 定义裁剪器的拖动模式。 移动画布
guides:false,
highlight:false,
background:false,
corp:(e)=>{
console.log('eeee',e)
}
};
option.preview = isPreview ? '.img_preview':'';
const newCropper = new Cropper(img, option, []);
setCropper(newCropper)
},[tailPic, isPreview]);
//取消
const reset = ()=>{
console.log('取消');
setTailPic(props.imgfile)
};
//剪切
const readied = async ()=>{
let newPic = cropper?.getCroppedCanvas([{
width:200,
height:200
}]).toDataURL('image/jpeg');
setTailPic(newPic);
};
//旋转
useEffect(()=>{
console.log('旋转到', rotate);
if( rotate === 360 || rotate === 0 ){
setRotate(0);
cropper?.reset()
}else{
cropper?.rotateTo(rotate)
}
},[ rotate ]);
const cancle = () =>{
// 返回上一页或者隐藏
};
const Ok = ()=>{
// tailPic:当前剪辑的图片给 onReady 回调函数
onReady()
};
return (
<div className={'tailor'} >
{ imgfile ?
[
<div className={'tail_top'}>
<div className={'btn'} onClick={cancle}> 取消</div>
<div className={'btn'} onClick={() => {setIsPreview( !isPreview )}}>
{!isPreview ? '开启预览' : '关闭预览'}
</div>
<div className={'btn'} onClick={Ok}> 确定</div>
</div>,
<div className={'tail_middle'} id={'tail_middle'}>
<img
id={'tailor_image'}
alt={'剪切图片'}
className={'tailor_image'}
/>
</div>,
<div className={'tail_buttom'}>
<div className={'btn'} onClick={reset}> 重置</div>
<div className={'btn'} onClick={() => {
setRotate(parseInt(rotate) + 90)
}}> 旋转
</div>
<div className="btn" onClick={readied}> 剪切</div>
</div>
]
:
<div className={'empty'}>暂无内容</div>
}
<div className={'img_preview'} />
</div>
)
};
export default Tailor;
css
// A code block
.tailor{
width: 100vw;
height: 100vh;
overflow: auto;
flex-direction: column;
display: flex;
background: #000;
position: relative;
}
.img_preview{
width: 150px;
height: 150px;
overflow: hidden;
position: absolute;
float: left;
top: 60px;
left: 40px;
border-radius: 8px;
}
.btn{
padding: 16px;
color: #ffffff;
font-size: 16px;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid;
}
.tail_top{
height: 40px;
padding: 8px;
display: flex;
justify-content: space-between;
}
.tail_middle{
overflow: hidden;
height: calc(100% - 112px);
display: flex;
justify-content: center;
align-items: center;
}
.tailor_image{
}
.tail_buttom{
height: 40px;
padding: 8px;
/*background: #ffffff;*/
display: flex;
justify-content: space-around;
}
.empty{
width: 100%;
height: 100%;
color: #ffffff;
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.tailor_image{
width: 100%;
}
.rotate >img{
width: 32px;
height: 32px;
}
效果图