我一直在尝试将 react-image-crop 与 react dropzone 连接起来,但这似乎不起作用,或者我做错了什么。
这是我的拖放组件
import { useDropzone } from 'react-dropzone';
import React, { useMemo, useCallback, useEffect, useRef } from 'react';
import styles from './index.module.scss';
import { FormField, FormCheckbox, Button } from 'components/common';
import toastr from 'utils/toastr';
import ModalInfoCrop from '../../../ModalnfoCrop';
const DragAndDrop = ({ value, onChange, field, form }) => {
const uploadInputRef = useRef(null);
useEffect(
() => () => {
files.forEach((file) => URL.revokeObjectURL(file.preview));
},
[files]
);
const files = useMemo(() => {
return (field && field.value) || value || [];
}, [field, value]);
const onFileAdd = useCallback(
(files) => {
if (field && form) {
form.setFieldValue(field.name, files);
} else {
onChange && onChange(files);
}
},
[field, form, onChange]
);
const error = useMemo(() => !!(field && form && form.errors[field.name]), [
field,
form,
]);
const { getRootProps, getInputProps } = useDropzone({
accept: 'image/*',
onDrop: (acceptedFiles) => {
let files_arr = files;
if (files.length) {
acceptedFiles.forEach((element) => {
if (element.size <= 15728640) {
let isRepeated = false;
files.forEach((file) => {
if (file.name === element.name) {
isRepeated = true;
return;
}
});
if (!isRepeated) {
files_arr.push(element);
}
} else {
toastr.error(`File ${element.name} is more than MB`);
}
});
} else {
files_arr = acceptedFiles;
}
onFileAdd(
files_arr.map((file) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
})
)
);
},
});
const changeMainPhoto = (e) => {
e.preventDefault();
let mainImageIndex = +e.target.getAttribute('data-fileindex');
form.setFieldValue('mainPhotoIndex', mainImageIndex);
};
const deletePhoto = (deletedIndex) => {
files.splice(deletedIndex, 1);
if (deletedIndex === form.values.mainPhotoIndex)
form.setFieldValue('mainPhotoIndex', 0);
onFileAdd(
files.map((file) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
})
)
);
};
const thumbs = files.map((file, index) => (
<div className={styles.thumb} key={index}>
<div className={styles.thumbInner}>
<img
src={(file && file.preview) || file}
className={styles.imgInner}
alt="item_photo"
/>
<FormCheckbox
value={form.values.mainPhotoIndex === index}
onClick={changeMainPhoto}
inputProps={{ 'data-fileindex': index }}
className={styles.mainImageCheckBox}
name=""
/>
<Button
onClick={() => deletePhoto(index)}
color="secondary"
className={styles.imageDeleteButton}
>
X
</Button>
</div>
</div>
));
return (
<>
<section className={error ? styles.wrapper_error : styles.wrapper}>
<div
{...getRootProps({ className: 'dropzone' })}
style={{
margin: '.5rem 1rem',
}}
>
<input
name="photos"
ref={uploadInputRef}
type="file"
{...getInputProps()}
/>
<p
style={{
margin: '.5rem auto',
fontWeight: '600',
}}
>
Drag Photos here <br /> or
</p>
<div
style={{
backgroundColor: 'black',
padding: '.5rem 1rem',
color: 'white',
borderRadius: '40px',
margin: '.5rem 30%',
}}
>
+ Add Photos
</div>
</div>
</section>
<aside className={styles.thumbsContainer}>{thumbs}</aside>
</>
);
};
export default ({ name, ...props }) =>
name ? (
<FormField name={name} component={DragAndDrop} {...props} />
) : (
<DragAndDrop {...props} />
);
这就是 react-image-crop 所在的地方,我在上传照片时尝试了多种打开裁剪的方法,但没有找到好的解决方案,所以删除了所有内容,这就是我现在的位置
import React, { Component, useState, useRef, useEffect, useCallback } from 'react';
import ReactCrop, { makeAspectCrop } from 'react-image-crop';
import { Button, Dialog, MuiThemeProvider } from '@material-ui/core';
import styles from './index.module.scss';
import { parseWithOptions } from 'date-fns/fp';
const pixelRatio = 4;
function getResizedCanvas(canvas, newWidth, newHeight) {
const tmpCanvas = document.createElement("canvas");
tmpCanvas.width = newWidth;
tmpCanvas.height = newHeight;
const ctx = tmpCanvas.getContext("2d");
ctx.drawImage(
canvas,
0,
0,
canvas.width,
canvas.height,
0,
0,
newWidth,
newHeight
);
return tmpCanvas;
}
function generateDownload(previewCanvas, crop) {
if (!crop || !previewCanvas) {
return;
}
const canvas = getResizedCanvas(previewCanvas, crop.width, crop.height);
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
);
}
export default function ModalInfoCrop(photo) {
const [upImg, setUpImg] = useState(photo);
const imgRef = useRef(photo);
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 && 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");
canvas.width = crop.width * pixelRatio;
canvas.height = crop.height * pixelRatio;
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
ctx.imageSmoothingEnabled = false;
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>
);
}
我只是不知道如何以正确的方式实现这一点,所以我很感激关于它的每一个建议,在此先感谢