Recomendado! Use react-cropper-pro para cortar, compactar e enviar imagens

No processo de desenvolvimento front-end, muitas vezes encontramos a necessidade de upload de arquivo ou upload de imagem. Em alguns cenários, pode ser necessário cortar e compactar a imagem após o upload. Para programadores que não querem trabalhar horas extras, o o primeiro ponto é usar bibliotecas de terceiros. Embora bibliotecas como antd, element e outras bibliotecas com as quais estamos familiarizados forneçam componentes de upload:

imagem.png

No entanto, por um lado, essas bibliotecas de interface do usuário de terceiros são relativamente grandes e não leves o suficiente e, por outro lado, não suportam funções como corte e compactação, portanto, ainda precisam implementar ou integrar bibliotecas de terceiros Obviamente antd, uma biblioteca antd-img-croppara corte de imagem é fornecida. No entanto, é extremamente "desconfortável" (restrito) de usar, incapaz de cortar livremente a imagem e também incapaz de fornecer recursos de compactação:

imagem.png

Portanto, esta solução também é simples pass. No final, para obter o efeito desejado, decidi me sacrificar e implementar manualmente um componente que suporta upload, recorte e compactação, e o nomeei react-cropper-pro.

2022-07-16 16.02.04.gif

Introdução ao uso de react-cropper-pro

react-cropper-proÉ um componente simples e leve de upload + recorte + compactação de imagens, que não depende antd / elementde interfaces de usuário de terceiros e pode implementar rapidamente operações relacionadas ao processamento de imagens, com dependências subjacentes react-cropper.

Instalar

yarn add react-cropper-pro

usar

import CropperPro from 'react-cropper-pro';

export default () => 
  <CropperPro 
    defaultImg="" 
    onChange={(file) => console.log(file)} 
    onDel={(image) => console.log('remove', image)} 
  />;

imagem.png

introdução da API

imagem.png

Realização técnica

Tecnicamente, existem os seguintes pontos principais:

  1. Implemente o estilo do componente de upload de arquivo (principalmente para substituir a "IU pura" do input[arquivo] nativo)
  2. Realize o corte repentino da imagem
  3. Implementar compactação de imagem
  4. Empacotado como um componente de reação e publicado no npm

A seguir, apresentaremos brevemente os detalhes da implementação.

1. Implemente o estilo do componente de upload de arquivo

imagem.png

Todos nós sabemos que o estilo padrão usado pelo componente de upload do arquivo de entrada do elemento é muito simples, então precisamos substituir o estilo nativo de alguma forma.Aqui vou compartilhar com vocês como eu o implementei.

imagem.png

Na verdade, é muito simples, basta usar o método de posicionamento para cobrir um div do mesmo tamanho na entrada e, em seguida, deixar o evento div penetrar e responder ao evento de entrada. O código principal é o seguinte:

<div className="xi-cropper-upload">
          <input type="file" onChange={handleChange} accept="image/gif,image/jpeg,image/jpg,image/png" />
          <div className="xi-cropper-file">
          </div>
</div>

A segunda é que após o usuário fazer o upload da imagem, a imagem pode ser exibida na área de upload, da seguinte forma:

imagem.png

O código completo para este bloco é o seguinte:

<div className="xi-cropper-upload">
          <input type="file" onChange={handleChange} accept="image/gif,image/jpeg,image/jpg,image/png" />
          <div className="xi-cropper-file">
            {
              cropData ? <img src={cropData} /> : '+'
            }
            {
              !!cropData && <span className="xi-cropper-del" onClick={handleDel}></span> 
            }
          </div>
        </div>

2. Realize o corte repentino da imagem

图片裁切这里我采用了 react-cropper 这个库, 虽然不能直接实现图片上传, 但是它的图片裁切能力还是很强大的. 我们需要实现的效果是图片上传后会出现上传弹窗, 显示裁切区域, 如下:

2022-07-16 16.02.04.gif

这里弹窗的实现我采用了React-Dom的createPortal API, 它可以实现弹窗dom挂载在指定的容器上, 很多组件库的组件比如抽屉, Modal, DropDown都采用了类似的实现原理, 我之前也写了一篇文章来介绍如何使用 createPortal 的, 感兴趣的朋友可以学习参考一下:

《精通react/vue组件设计》之配合React Portals实现一个功能强大的抽屉(Drawer)组件

这块的核心源码可以参考github仓库对应的第134行.

文件路径如下: github.com/MrXujiang/r…

3. 实现图片压缩

图片压缩这块主要是基于产品业务场景来设计, 这里我分了4个档:

  • 不压缩

如下:

imagem.png

这一块主要是利用了canvascropper 的能力, 我们通过控制canvas对象的宽高比例, 和canvas提供的toBlob 来实现图片的压缩, 核心代码如下:

if (typeof cropper !== "undefined") {
      setCropData(cropper.getCroppedCanvas().toDataURL());
      const rate = 1 / (4 - imgLevel);
      const { width, height } = cropper.getCropBoxData();
      cropper.getCroppedCanvas({
        width: width * rate,
        height: height * rate,
        imageSmoothingQuality: imgLevelValueMap[imgLevel],
        fillColor: 'transparent',
      }).toBlob((blob: Blob) => {
        if(blob) {
          const time = Date.now();
          let croppedFile:any = new File([blob], fileRef.current.name, {
            type: fileRef.current.type,
            lastModified: Date.now(),
          });
          croppedFile.uid = time;
          onChange && onChange(croppedFile)
        }else {
          new Error('图片裁切失败');
        }
        
      }, fileRef.current.type, rate)
    }

当然有关 canvastoBlob API不熟悉的朋友可以移步MDN:

developer.mozilla.org/zh-CN/docs/…

4. 包装成react组件并发布到npm

有关如何实现组件库以及如何优雅发布到NPM公仓的技术我之前在《趣谈前端》 也分享过, 感兴趣的朋友可以参考一下: 从零教你搭建组件系统《高级进阶必备》

应用场景

Por fim, vamos dar uma olhada no cenário de aplicação, que react-cropper-profoi aplicado à H5-Dooringplataforma de construção visual para obter um controle mais preciso das imagens:

imagem.png

Amigos interessados ​​podem experimentá-lo. Claro, existem muitas plataformas de conteúdo. Devido à capacidade de escrita de editores como rich text ou md, também envolverá o controle de imagens, portanto, essas são react-cropper-proas áreas de aplicação do .

afinal

O código aberto não é fácil, bem-vindo para construir e construir juntos, clique em uma estrela para tornar a vida melhor.

おすすめ

転載: juejin.im/post/7121218571136401422