React使用react-cropper实现图片裁剪上传

由于实在太多人遇到了问题, 特意提供了一个小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'
            />

重要的属性:

  1. src - 目标图片的url
  2. 其他的options 可以参考这里 (react版与jQuery版options是相通的)
  3. 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()
      })
    }
  }
  1. 实现效果


    实现效果图
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,374评论 19 139
  • 我希望可以躺在向日葵上 即使沮丧悲伤 也能面向阳光
    琉_璃阅读 1,885评论 8 1
  • 早上起来去上班,到了厂里通知我们机器还没有搞好,让我们回去。郁闷啊! 出了厂里,我去银行办理业务,先是淘宝的登录密...
    月儿的2016阅读 1,820评论 1 2
  • 【导读】20年间,马云不断地将电子商务的概念向世人推广深入,至今,电子商务充其量只占全球28万亿美元全球零售市场的...
    北斗书院阅读 1,618评论 0 0
  • 感觉生活就像一个 又一个的牢笼 困住了人的一生 当今天的破了 碎了 明天的以为你备好 以 人生为基础 时间为链...
    镜中女巫阅读 891评论 0 0