常用的文件上传场景 https://juejin.cn/post/6980142557066067982

image.png

ReactImageCrop裁剪图片

https://github.com/DominicTobias/react-image-crop

  1. npm i react-image-crop
  1. function CropDemo({ src }) {
  2. const [crop, setCrop] = useState({ aspect: 16 / 9 });
  3. return <ReactCrop src={src} crop={crop} onChange={newCrop => setCrop(newCrop)} />;
  4. }

裁剪图片demo
https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o?file=/src/App.js:0-3132

  1. import React, { useState, useCallback, useRef, useEffect } from 'react';
  2. import ReactCrop from 'react-image-crop';
  3. import 'react-image-crop/dist/ReactCrop.css';
  4. function App() {
  5. const [upImg, setUpImg] = useState();
  6. const imgRef = useRef(null);
  7. const previewCanvasRef = useRef(null);
  8. const [crop, setCrop] = useState({ unit: '%', width: 30, aspect: 16 / 9 });
  9. const [completedCrop, setCompletedCrop] = useState(null);
  10. const onSelectFile = (e) => {
  11. if (e.target.files?.length > 0) {
  12. const reader = new FileReader();
  13. reader.addEventListener('load', () => setUpImg(reader.result));
  14. reader.readAsDataURL(e.target.files[0]);
  15. }
  16. };
  17. const onLoad = useCallback((img) => {
  18. imgRef.current = img;
  19. }, []);
  20. useEffect(() => {
  21. if (!completedCrop || !previewCanvasRef.current || !imgRef.current) {
  22. return;
  23. }
  24. const image = imgRef.current;
  25. const canvas = previewCanvasRef.current;
  26. const crop = completedCrop;
  27. const scaleX = image.naturalWidth / image.width;
  28. const scaleY = image.naturalHeight / image.height;
  29. const ctx = canvas.getContext('2d');
  30. const pixelRatio = window.devicePixelRatio;
  31. canvas.width = crop.width * pixelRatio;
  32. canvas.height = crop.height * pixelRatio;
  33. ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
  34. ctx.imageSmoothingQuality = 'high';
  35. ctx.drawImage(
  36. image,
  37. crop.x * scaleX,
  38. crop.y * scaleY,
  39. crop.width * scaleX,
  40. crop.height * scaleY,
  41. 0,
  42. 0,
  43. crop.width,
  44. crop.height
  45. );
  46. }, [completedCrop]);
  47. return (
  48. <div className="App">
  49. <div>
  50. <input type="file" accept="image/*" onChange={onSelectFile} />
  51. </div>
  52. <ReactCrop
  53. src={upImg}
  54. onImageLoaded={onLoad}
  55. crop={crop}
  56. onChange={(c) => setCrop(c)}
  57. onComplete={(c) => setCompletedCrop(c)}
  58. />
  59. <div>
  60. <canvas
  61. ref={previewCanvasRef}
  62. // Rounding is important so the canvas width and height matches/is a multiple for sharpness.
  63. style={{
  64. width: Math.round(completedCrop?.width ?? 0),
  65. height: Math.round(completedCrop?.height ?? 0)
  66. }}
  67. />
  68. </div>
  69. <p>
  70. Note that the download below won't work in this sandbox due to the
  71. iframe missing 'allow-downloads'. It's just for your reference.
  72. </p>
  73. <button
  74. type="button"
  75. disabled={!completedCrop?.width || !completedCrop?.height}
  76. onClick={() =>
  77. generateDownload(previewCanvasRef.current, completedCrop)
  78. }
  79. >
  80. 下载图片
  81. </button>
  82. </div>
  83. );
  84. }
  85. export default App;
  86. // 下载图片
  87. function generateDownload(canvas, crop) {
  88. if (!crop || !canvas) {
  89. return;
  90. }
  91. canvas.toBlob(
  92. (blob) => {
  93. const previewUrl = window.URL.createObjectURL(blob);
  94. const anchor = document.createElement('a');
  95. anchor.download = 'cropPreview.png';
  96. anchor.href = URL.createObjectURL(blob);
  97. anchor.click();
  98. window.URL.revokeObjectURL(previewUrl);
  99. },
  100. 'image/png',
  101. 1
  102. );
  103. }

antd-img-crop图片裁剪

基于 react-easy-crop和 antd Modal的图片上传封装
图片裁剪是基于 Modal的弹窗,缺点

function ImageCrop() { const [fileList, setFileList] = useState([ { uid: ‘-1’, url: ‘https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png‘, }, ]);

const onChange = ({ fileList: newFileList }) => { setFileList(newFileList); };

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

return ( {fileList.length < 3 && ‘+ Upload’} ); };

export default ImageCrop;

  1. <a name="CI3L6"></a>
  2. ### react-easy-crop
  3. antd-img-crop就是对 react-easy-crop的封装<br />[https://github.com/ricardo-ch/react-easy-crop](https://github.com/ricardo-ch/react-easy-crop)
  4. ```bash
  5. yarn add react-easy-crop

image.png