由于实在太多人遇到了问题, 特意提供了一个小demo供大家参考, demo中分别用React的class component形式和Hooks形式实现了两个同样功能的图片裁剪弹窗. 参考代码地址: https://github.com/qhwc2009/copper-learn
你可以把demo工程clone下来到本地, 然后执行
$ yarn
, 执行完毕后再执行$ yarn start
启动项目.
用到的组件
实现图片裁切并上传, 本文用到了:
- html input标签的type=file属性
- react-cropper库
实现步骤
1. 在外面的view页面上, 利用input实现上传的图片暂存
<label className="add-img-btn">
<span>添加图片</span>
<input
type="file"
accept="image/jpeg,image/jpg,image/png"
className="base-upload-input"
onChange={this.handleFileChange}
/>
</label>
可以把input 隐藏起来
之后, 把通过input上传的文件暂存在state中
handleFileChange = (e) => {
const file = e.target.files[0]
if (file) {
if (file.size <= MAX_FILE_SIZE) {
this.setState({
selectedImageFile: file,
}, () => {
this.setState({
editImageModalVisible: true,
})
})
} else {
message.error("文件过大")
}
}
e.target.value = ''
}
2. 弹出图片裁剪的Modal窗口(我把窗口抽离成了一个独立的组件)
窗口可以自己写, 这里贴出核心代码
这里使用了react-cropper库
弹出弹框来,之后
首先, 要把上一个步骤中储存在state中的文件转化成能读取的URL
通过this.props.uploadedImageFile
属性把之前存的图片传进来, 读取, 读取完毕设置上src, 给下一步用
componentDidMount() {
const fileReader = new FileReader()
fileReader.onload = (e) => {
const dataURL = e.target.result
this.setState({src: dataURL})
}
fileReader.readAsDataURL(this.props.uploadedImageFile)
}
接下来是图片图调用代码
这里要使用上面读取的src
<Cropper
src={this.state.src}
className="company-logo-cropper"
ref={cropper => this.cropper = cropper}
// Cropper.js options
viewMode={1}
zoomable={false}
aspectRatio={1} // 这个是设置比例的参数 我这里设置的1:1
guides={false}
preview='.cropper-preview'
/>
重要的属性:
- src - 目标图片的url
- 其他的options 可以参考这里 (react版与jQuery版options是相通的)
- cropper-preview 这里指定类名为cropper-preview的div作为预览的窗口
3. 提交裁剪好的图片
handleSubmit = () => {
if (!this.state.submitting) {
let url = `/homepage_images`
// 拿到文件名
let filename = this.props.uploadedImageFile.name
message.info("正在上传图片")
// TODO: 这里可以尝试修改上传图片的尺寸
this.cropper.getCroppedCanvas().toBlob(async blob => {
// 创造提交表单数据对象
const formData = new FormData()
// 添加要上传的文件
formData.append('file', blob, filename)
// 提示开始上传
this.setState({submitting: true})
// 上传图片
const resp = await http.post(url, formData)
// 拿到服务器返回的数据
this.props.onUploadedFile(resp.data.data)
// 提示上传完毕
this.setState({submitting: false})
// 关闭弹窗
this.props.onClose()
})
}
}
-
实现效果