feat: add image crop modal

This commit is contained in:
Kentai Radiquum 2024-08-17 19:28:35 +05:00
parent 530fc1aad0
commit 5cde53c1d3
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
5 changed files with 202 additions and 21 deletions

View file

@ -0,0 +1,115 @@
import React, { useRef } from "react";
import Cropper, { ReactCropperElement } from "react-cropper";
import "cropperjs/dist/cropper.css";
import { Button, Modal } from "flowbite-react";
import { b64toBlob } from "#/api/utils";
type Props = {
src: string;
setSrc: (src: string) => void;
setTempSrc: (src: string) => void;
setImageData: (src: string) => void;
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
height: number;
width: number;
aspectRatio: number;
guides: boolean;
quality: number;
forceAspect?: boolean;
};
export const CropModal: React.FC<Props> = (props) => {
const cropperRef = useRef<ReactCropperElement>(null);
const getCropData = () => {
if (typeof cropperRef.current?.cropper !== "undefined") {
props.setSrc(cropperRef.current?.cropper.getCroppedCanvas().toDataURL());
let block = cropperRef.current?.cropper
.getCroppedCanvas({
width: props.width,
height: props.height,
maxWidth: props.width,
maxHeight: props.height,
})
.toDataURL("image/jpeg", props.quality)
.split(";");
let contentType = block[0].split(":")[1];
let realData = block[1].split(",")[1];
const blob = b64toBlob(realData, contentType);
const handleFileRead = (e, fileReader) => {
const content = fileReader.result;
props.setImageData(content);
};
const handleFileText = (file) => {
const fileReader = new FileReader();
fileReader.onloadend = (e) => {
handleFileRead(e, fileReader);
};
fileReader.readAsText(file);
};
handleFileText(blob);
props.setTempSrc("");
}
};
return (
<Modal
dismissible
show={props.isOpen}
onClose={() => props.setIsOpen(false)}
size={"7xl"}
>
<Modal.Header>Обрезать изображение</Modal.Header>
<Modal.Body>
<Cropper
src={props.src}
style={{ height: 400, width: "100%" }}
responsive={true}
// Cropper.js options
initialAspectRatio={props.aspectRatio}
aspectRatio={props.forceAspect ? props.aspectRatio : undefined}
guides={props.guides}
ref={cropperRef}
/>
<div className="mt-4">
<h2 className="font-bold text-md">Управление</h2>
<p>Тяните за углы что-бы выбрать область</p>
<p>
Нажмите 2 раза на пустое место, что бы поменять режим выбора области
на перемещение и обратно
</p>
<p>Используйте колёсико мыши что-бы изменить масштаб</p>
</div>
</Modal.Body>
<Modal.Footer>
<Button
color={"blue"}
onClick={() => {
getCropData();
props.setIsOpen(false);
}}
>
Сохранить
</Button>
<Button
color={"red"}
onClick={() => {
props.setSrc(null);
props.setTempSrc(null);
props.setImageData(null);
props.setIsOpen(false);
}}
>
Удалить
</Button>
</Modal.Footer>
</Modal>
);
};