react截图

antd 官方提供的剪切组件 仅支持本地图片的剪切和上传 import { Upload } from 'antd' ; import ImgCrop from 'antd-img-crop' ; import type { RcFile, UploadFile, UploadProps } from '

antd 官方提供的剪切组件

仅支持本地图片的剪切和上传

import { Upload } from 'antd';
import ImgCrop from 'antd-img-crop';
import type { RcFile, UploadFile, UploadProps } from 'antd/es/upload/interface';
import React, { useState } from 'react';

const App: React.FC = () => {
  const [fileList, setFileList] = useState<UploadFile[]>([
    {
      uid: '-1',
      name: 'image.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    },
  ]);

  const onChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
    setFileList(newFileList);
  };

  const onPreview = async (file: UploadFile) => {
    let src = file.url as string;
    if (!src) {
      src = await new Promise((resolve) => {
        const reader = new FileReader();
        reader.readAsDataURL(file.originFileObj as RcFile);
        reader.onload = () => resolve(reader.result as string);
      });
    }
    const image = new Image();
    image.src = src;
    const imgWindow = window.open(src);
    imgWindow?.document.write(image.outerHTML);
  };

  return (
    <ImgCrop rotate>
      <Upload
        action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
        listType="picture-card"
        fileList={fileList}
        onChange={onChange}
        onPreview={onPreview}
      >
        {fileList.length < 5 && '+ Upload'}
      </Upload>
    </ImgCrop>
  );
};

export default App;

Demo

demo地址: antd 官方提供的剪切组件

在这里插入图片描述

react-easy-corp

antd的剪切组件就是基于此依赖封装

import React, { useState, useCallback } from 'react';
import Cropper from 'react-easy-crop';

const yourImage = 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png';

const Demo = () => {
  const [crop, setCrop] = useState({ x: 0, y: 0 });
  const [zoom, setZoom] = useState(1);

  const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => {
    console.log(croppedArea, croppedAreaPixels);
  }, []);

  return (
    <div style={{ position: 'relative', width: 300, height: 300 }}>
      <Cropper
        image={yourImage}
        crop={crop}
        zoom={zoom}
        aspect={4 / 3}
        onCropChange={setCrop}
        onCropComplete={onCropComplete}
        onZoomChange={setZoom}
      />
    </div>
  );
};

export default Demo;

Demo

demo地址: react-easy-crop

在这里插入图片描述

react-easy-corp-showImg

基于react-easy-corp,增加了生成剪切后图片blob功能

import { Button, message } from 'antd';
import React, { useState, useEffect, useCallback } from 'react';
import Cropper from 'react-easy-crop';
import type { Area } from 'react-easy-crop/types';
import styles from './ReactEasyCropShowImg.less';
const yourImage = 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png';
const PREFIX = 'tds';

export interface ReactEasyCropShowImgProps extends React.HTMLAttributes<HTMLDivElement> {}

const ReactEasyCropShowImg = (props: ReactEasyCropShowImgProps) => {
  const { className = '', ...otherProps } = props;
  const [crop, setCrop] = useState({ x: 0, y: 0 });
  const [zoom, setZoom] = useState(1);
  const [resultUrl, setResultUrl] = useState('');
  const [croppedAreaPixels, setCroppedAreaPixels] = useState({ x: 0, y: 0, width: 0, height: 0 });

  const onCropComplete = useCallback((croppedArea: Area, croppedAreaPixels: Area) => {
    console.log(croppedArea, croppedAreaPixels);
    setCroppedAreaPixels(croppedAreaPixels);
  }, []);

  useEffect(() => {
    const imgSource = document.querySelector(`.${PREFIX}-media`) as HTMLImageElement;
    imgSource.setAttribute('crossOrigin', 'Anonymous'); // 处理跨域
    imgSource.onload = () => {
      // 加载图像完成之后
      console.log('图片已添加允许跨域的属性');
    };
  }, []);

  const onOk = () => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
    const { width: cropWidth, height: cropHeight, x: cropX, y: cropY } = croppedAreaPixels;
    const imgSource = document.querySelector(`.${PREFIX}-media`) as HTMLImageElement;
    canvas.width = cropWidth;
    canvas.height = cropHeight;
    // ctx.fillStyle = fillColor;
    ctx.fillRect(0, 0, cropWidth, cropHeight);
    ctx.drawImage(imgSource, cropX, cropY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);
    try {
      canvas.toBlob((blob) => {
        if (blob) {
          console.log('blob', blob);
          const blobUrl = window.URL.createObjectURL(blob);
          console.log('blobUrl', blobUrl);
          setResultUrl(blobUrl);
        }
      });
    } catch (error) {
      message.error('无法导出受污染的画布');
      console.log('无法导出受污染的画布', error);
    }
  };
  return (
    <div className={`${styles.root} ${className}`} {...otherProps}>
      <h2>Crop 操作区</h2>
      <div className={styles.cropBox}>
        <Cropper
          image={yourImage}
          showGrid={false}
          crop={crop}
          zoom={zoom}
          aspect={4 / 3}
          onCropChange={setCrop}
          onCropComplete={onCropComplete}
          onZoomChange={setZoom}
          classes={{
            containerClassName: `${PREFIX}-container`,
            mediaClassName: `${PREFIX}-media`,
          }}
        />
      </div>
      <div style={{ marginTop: 12, marginBottom: 12 }}>
        <Button onClick={onOk}>生成剪切结果</Button>
      </div>
      <h2>剪切结果</h2>
      <img className={styles.resultImg} src={resultUrl}></img>
    </div>
  );
};

export default ReactEasyCropShowImg;

Demo

demo地址: react-easy-crop-showImg

在这里插入图片描述

知秋君
上一篇 2024-07-06 09:48
下一篇 2024-07-06 09:12

相关推荐