常用的文件上传场景 https://juejin.cn/post/6980142557066067982
ReactImageCrop裁剪图片
https://github.com/DominicTobias/react-image-crop
npm i react-image-crop
function CropDemo({ src }) {
const [crop, setCrop] = useState({ aspect: 16 / 9 });
return <ReactCrop src={src} crop={crop} onChange={newCrop => setCrop(newCrop)} />;
}
裁剪图片demo
https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o?file=/src/App.js:0-3132
import React, { useState, useCallback, useRef, useEffect } from 'react';
import ReactCrop from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';
function App() {
const [upImg, setUpImg] = useState();
const imgRef = useRef(null);
const previewCanvasRef = useRef(null);
const [crop, setCrop] = useState({ unit: '%', width: 30, aspect: 16 / 9 });
const [completedCrop, setCompletedCrop] = useState(null);
const onSelectFile = (e) => {
if (e.target.files?.length > 0) {
const reader = new FileReader();
reader.addEventListener('load', () => setUpImg(reader.result));
reader.readAsDataURL(e.target.files[0]);
}
};
const onLoad = useCallback((img) => {
imgRef.current = img;
}, []);
useEffect(() => {
if (!completedCrop || !previewCanvasRef.current || !imgRef.current) {
return;
}
const image = imgRef.current;
const canvas = previewCanvasRef.current;
const crop = completedCrop;
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
const ctx = canvas.getContext('2d');
const pixelRatio = window.devicePixelRatio;
canvas.width = crop.width * pixelRatio;
canvas.height = crop.height * pixelRatio;
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
ctx.imageSmoothingQuality = 'high';
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height
);
}, [completedCrop]);
return (
<div className="App">
<div>
<input type="file" accept="image/*" onChange={onSelectFile} />
</div>
<ReactCrop
src={upImg}
onImageLoaded={onLoad}
crop={crop}
onChange={(c) => setCrop(c)}
onComplete={(c) => setCompletedCrop(c)}
/>
<div>
<canvas
ref={previewCanvasRef}
// Rounding is important so the canvas width and height matches/is a multiple for sharpness.
style={{
width: Math.round(completedCrop?.width ?? 0),
height: Math.round(completedCrop?.height ?? 0)
}}
/>
</div>
<p>
Note that the download below won't work in this sandbox due to the
iframe missing 'allow-downloads'. It's just for your reference.
</p>
<button
type="button"
disabled={!completedCrop?.width || !completedCrop?.height}
onClick={() =>
generateDownload(previewCanvasRef.current, completedCrop)
}
>
下载图片
</button>
</div>
);
}
export default App;
// 下载图片
function generateDownload(canvas, crop) {
if (!crop || !canvas) {
return;
}
canvas.toBlob(
(blob) => {
const previewUrl = window.URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.download = 'cropPreview.png';
anchor.href = URL.createObjectURL(blob);
anchor.click();
window.URL.revokeObjectURL(previewUrl);
},
'image/png',
1
);
}
antd-img-crop图片裁剪
基于 react-easy-crop和 antd Modal的图片上传封装
图片裁剪是基于 Modal的弹窗,缺点
- 没有设置 mask: false,如果页面上有 Modal了,上传图片会有 mask覆盖
在线demo https://codesandbox.io/s/antd-img-crop-4qoom5p9x4?file=/src/index.jsyarn add antd-img-crop
在线源码 https://github.com/nanxiaobei/antd-img-crop/blob/master/src/index.jsx
属性
```jsx import React, { useState } from ‘react’; import { Upload } from ‘antd’; import ImgCrop from ‘antd-img-crop’;
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 (
export default ImageCrop;
<a name="CI3L6"></a>
### react-easy-crop
antd-img-crop就是对 react-easy-crop的封装<br />[https://github.com/ricardo-ch/react-easy-crop](https://github.com/ricardo-ch/react-easy-crop)
```bash
yarn add react-easy-crop