react-cropper图片裁剪,旋转应用

最近写项目,遇到一个有意思的需求,分享一下实现过程:

需求简单描述:对现有图片(网络路径)进行裁剪,也可以上传一张图片进行裁剪,旋转,达到自己想要的效果。

应用技术:react hook,ant-design,react-cropper(插件)

项目中需要安装插件:

npm install react-cropper --save-dev

注:这里用的react-crooper 版本号 @1.2.0 ,不同版本存在使用中的差异,所以这里注明当前例子使用的是1.2.0。

组件中引用:

import Cropper from 'react-cropper';
import 'cropperjs/dist/cropper.css';

注:因项目中webpack配置的打包编译在css-loader这一块配置的时候,exclude 了node_module包中对css的编译,导致引入插件后编译通不过,需要 【include: [/[\\/]node_modules[\\/].*cropperjs/],】添加对cropperjs中的css进行编译操作。

父组件操作:

import React from 'react'

import CropperModal from './CropperModal'

import { getBase64Image, main } from 'utils'
const url = 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
export default () => {
    const [hooksModalFile,setHooksModalFile] = React.useState();
    const [modalVisible, setModalVisible] = React.useState();
    useEffect(()=>{
        main(userDetail.avatarUrl, (base64) => {
            const file = base64toFile(base64, '图片名称');
            setHooksModalFile(file);
            setModalVisible(true);

        });
    },[hooksModalFile]);

    const getNewImgUrl = (event) => {
        // 转化后,并且已上传到图片库中的图片路径
    };
    return  {
              setModalVisible(false);
            }}
            onSubmit={getNewImgUrl}
          />
}

具体实现:

import React, { useState, useEffect, useCallback, useRef } from 'react'
import { Button, Upload } from 'antd';
import Cropper from 'react-cropper' // 引入Cropper
import 'cropperjs/dist/cropper.css' // 引入Cropper对应的css

import './index.scss'

export default ({ uploadedImageFile, onClose, onSubmit }) => {
  const [src, setSrc] = useState(null);
  const [fileList, setFileList] = React.useState([]);
  const cropperRef = useRef(null);
  const uploadProps = {
        beforeUpload: file1 => {
            setFileList([file1]);
            setIsShow(false);
            const fileReader = new FileReader();
            fileReader.onload = e => {
                const dataURL = e.target.result;
                setNewSrc(dataURL);
            };
            fileReader.readAsDataURL(file1);
            return false;
        },
        multiple: false,
        accept: '.png, .jpeg, .jpg',
    };

  useEffect(() => {
    const fileReader = new FileReader()
    fileReader.onload = e => {
      const dataURL = e.target.result
      setSrc(dataURL)
    }

    fileReader.readAsDataURL(uploadedImageFile)
  }, [uploadedImageFile])

  const handleSubmit = useCallback(() => {
    console.log('正在上传图片')
    // TODO: 这里可以尝试修改上传图片的尺寸
    cropperRef.current.getCroppedCanvas().toBlob(async blob => {
      console.log('blob', blob);
      // 创造提交表单数据对象
      const formData = new FormData()
      // 添加要上传的文件
      // formData.append('file', blob, filename)
      // 提示开始上传 (因为demo没有后端server, 所以这里代码我注释掉了, 这里是上传到服务器并拿到返回数据的代码)
      // 上传图片
      // 此处实现上传操作 ajax请求
      // 提示上传完毕

      //把选中裁切好的的图片传出去
      onSubmit(blob)

      // 关闭弹窗
      onClose()
    })
  }, [onClose, onSubmit])

  return (
    
点击提交
) }

工具准备:

1. 需要将拿到的网络图片地址url,转化为文件类型格式(转化方式:a.需要将url转化为base64格式;b. base64格式转为文件类型)

const getBase64Image = (img) => {
  const canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0, img.width, img.height);
  const dataURL = canvas.toDataURL('image/png'); // 可选其他值 image/jpeg
  return dataURL;
};

const main = (src, cb) => {
  const image = new Image();
  image.src = `${src}?v=${Math.random()}`; // 处理缓存
  image.crossOrigin = '*'; // 支持跨域图片
  image.onload = function() {
    const base64 = getBase64Image(image);
    cb && cb(base64);
  };
};

export { getBase64Image, main };

图片添加旋转功能:

const rotateClick = () => {
    console.log('cropperRef',cropperRef.current)
    cropperRef.current.cropper.rotate(90);
}

index.sass文件:

.hooks-cropper-modal {
  position: fixed;
  background-color: rgba(#000000, 0.3);
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;

  .modal-panel {
    width: 880px;
    height: 500px;
    background: white;
    padding: 20px;
    display: flex;
    flex-direction: column;
    align-items: stretch;

    .button-row {
      height: 50px;
      flex-shrink: 0;
      display: flex;
      justify-content: center;
      .submit-button {
        padding: 0 20px;
        height: 100%;
        color: #383838;
        font-size: 14px;
      }
    }

    .cropper-container-container {
      flex: 1;
      display: flex;
      align-items: stretch;
      justify-content: space-between;
      height: 100%;

      .cropper-container {
        flex: 0 0 600px;
        margin-right: 20px;
        .cropper {
          width: 100%;
          height: 100%;
        }
      }
      .preview-container {
        flex: 1;
        display: flex;
        align-items: flex-end;
        .cropper-preview {
          width: 180px;
          height: 180px;
          overflow: hidden;
          border: 1px solid #383838;
        }
      }
    }
  }
}

此次实现过程时间较短,功能实现相对粗糙了些,但基本需求效果均已实现,欢迎大佬们提出你的宝贵建议。

 

 

 

 

 

你可能感兴趣的:(react,reactjs)