zoukankan      html  css  js  c++  java
  • react 项目里 实现图片剪裁

    1.安装模块

    yarn add react-cropper lrz

    2.分装组件

    src/components/ImgCropper/index.tsx

    /**
     * 上传logo组件
     */
    import * as React from 'react';
    import { Upload, Icon, message, Modal, Button } from 'antd';
    // 图片剪裁
    import Cropper from 'react-cropper';
    // 图片压缩
    // import lrz from 'lrz';
    // base64 转 Blob
    import { b64toBlob } from '@utils/b64toBlob';
    import { BaseUrl } from '@utils/constants';
    import 'cropperjs/dist/cropper.css';
    import axios from 'axios';
    import './index.less';
    
    const lrz = require('lrz');
    
    interface IProps {
      onSuccess?: Function | any;
      onChange?: Function | any;
      title: string;
      aspectRatio?: number;
    }
    
    interface IState {
      srcCropper: any;
      visible: boolean;
      confirmLoading: boolean;
    }
    
    class ImgCropper extends React.Component<IProps, IState>{
      constructor(props: IProps){
        super(props);
        this.state = {
          srcCropper: '',
          visible: false,
          confirmLoading: false
        }
      }
    
      beforeUpload = (file: any) => {
        const isLt10M = file.size / 1024 / 1024 < 10;
        if (!isLt10M) {
          // 添加文件限制
          message.error({ content: '文件大小不能超过10M' });
          return false;
        }
        const reader = new FileReader();
        reader.readAsDataURL(file); // 开始读取文件
        // 因为读取文件需要时间,所以要在回调函数中使用读取的结果
        reader.onload = (e: any) => {
          this.setState({
            visible: true,
            srcCropper: e.target.result, // cropper的图片路径
          });
        };
        return false;
      };
    
      saveImg = () => {
        this.setState({
          confirmLoading: true,
        });
        // 通过refs读取到Cropper实例,并读取到裁剪之后的图片(base64)
        const cropper: any =  this.refs.cropper;
        const url = cropper.getCroppedCanvas().toDataURL();
        // 此处使用了lrz组件对裁剪之后的图片进行压缩,lrz的API十分简单,quality是指对压缩图片的品质,一般0.6或者0.7即可
        lrz(url, { quality: 0.6 }).then((results: any) => {
          const { onSuccess, onChange } = this.props;
          const fd = new FormData();
          // 由于后台接口参数需要一个文件名,所有根据当前时间生成文件名
          const imgName = `${new Date().getTime()}.png`;
          // 将base64转化成二进制流
          fd.append('file', b64toBlob(results.base64), imgName);
          // 发送请求
          axios.post(`${BaseUrl}/tools/saveAvatar`, fd).then((res) => {
            const { data={} } = res;
            if(data.code === 200){
              onSuccess(data.data.file);
              onChange && onChange(data.data.file);
              message.success(data.message || '上传成功');
            }
          }).catch((err) => {
            message.error('上传失败');
          }).finally(() => this.onCloseModal())
        });
      };
    
      // 取消
      onCloseModal = () => {
        this.setState({
          visible: false,
          confirmLoading: false
        })
      }
      
      render() {
        // 考虑靠组件复用,裁剪Modal的标题作为属性从组件外部传递进来
        const { title, aspectRatio=1 } = this.props;
        /**
         * srcCropper:cropper组件内部图片的url
         * visible:裁剪Modal的显示属性
         * confirmLoading:图片上传过程中Modal的Loading效果
         * */
        const { srcCropper, visible, confirmLoading } = this.state;
        return (
          <div>
            <Upload beforeUpload={this.beforeUpload} showUploadList={false}>
              <Button>
                <Icon type="upload" /> 选择图片
              </Button>
            </Upload>
            <Modal
              title={title}
              visible={visible}
              onOk={this.saveImg}
              onCancel={this.onCloseModal}
              okText="确认上传"
              cancelText="取消"
              confirmLoading={confirmLoading}
            >
              {/* <div className="previewHeader">
                {srcCropper ? (
                  <div className="previewOutter">
                    <div className="uploadCrop previewContainer" />
                    <div className="uploadCropcir previewContainer" />
                  </div>
                ) : (
                  ''
                )}
              </div> */}
              {srcCropper ? (
                <Cropper
                  ref="cropper"
                  style={{ height: 400,  '100%' }}
                  // 预览图的容器
                  preview=".previewContainer"
                  guides
                  // 固定图片裁剪比例(正方形)
                  aspectRatio={aspectRatio}
                  // 要裁剪的图片的路径
                  src={srcCropper}
                />
              ) : (
                ''
              )}
            </Modal>
          </div>
        );
      }
    }
    
    export default ImgCropper;

    3.页面调用

    <Form.Item label="头像">
      {getFieldDecorator('avatar', {
        rules: [{ required: true, message: '请上传头像' }],
        initialValue: detail['avatar'] || undefined
      })(<ImgCropper title="上传头像" onSuccess={this.handleSuccess} />)}
      {(avatarImg || detail['avatar']) && <img className="avatar-img" src={avatarImg || detail['avatar']} alt="头像" /> || null}
    </Form.Item>
    

    .

  • 相关阅读:
    vim 颜色主题设置
    给vim安装YouCompleteMe
    linux的主题与图标
    arch点击硬盘无法挂载
    arch安装完成之后不能使用笔记本自带的无线网卡
    curl的使用
    arch优化开机
    seo成功案例的背后秘密
    网站seo整站优化有什么优势
    企业站如何做长尾关键词seo优化
  • 原文地址:https://www.cnblogs.com/crazycode2/p/12574129.html
Copyright © 2011-2022 走看看