import React, { FC, useRef, useState } from "react"; import { saveAs } from "file-saver"; import ReactCrop, { Crop } from "react-image-crop"; import "react-image-crop/dist/ReactCrop.css"; import { Box, Button, Modal, Slider, Typography } from "@mui/material"; import quiz from "../../assets/quiz-template-6.png"; import { ResetIcon } from "@icons/ResetIcon"; interface Iprops { opened: boolean; onClose: () => void; } const style = { position: "absolute" as "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", width: "620px", bgcolor: "background.paper", boxShadow: 24, padding: "20px", borderRadius: "8px", }; const styleSlider = { width: "250px", color: "#7E2AEA", height: "12px", "& .MuiSlider-track": { border: "none", }, "& .MuiSlider-rail": { backgroundColor: "#F2F3F7", border: `1px solid "#9A9AAF"`, }, "& .MuiSlider-thumb": { height: 26, width: 26, border: `6px solid #7E2AEA`, backgroundColor: "white", boxShadow: `0px 0px 0px 3px white, 0px 4px 4px 3px #C3C8DD`, "&:focus, &:hover, &.Mui-active, &.Mui-focusVisible": { boxShadow: `0px 0px 0px 3px white, 0px 4px 4px 3px #C3C8DD`, }, }, }; export const CroppingModal: FC = ({ opened, onClose }) => { const [src, setSrc] = useState(quiz); const [crop, setCrop] = useState({ unit: "px", y: 0, x: 0, width: 100, height: 100 }); const [completedCrop, setCompletedCrop] = useState(null); const [imageSize, setImageSize] = useState(580); const [darken, setDarken] = useState(0); const fileInputRef = useRef(null); const onCropComplete = (crop: Crop) => { setCompletedCrop(crop); }; const handleFileChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { const file = e.target.files[0]; const reader = new FileReader(); reader.onload = (event) => { if (event.target && event.target.result) { setSrc(event.target.result); } }; reader.readAsDataURL(file); } }; const handleDownloadClick = async () => { if (completedCrop && src) { const croppedImageUrl = await getCroppedAndDarkenedImg(src, completedCrop, "cropped.jpeg", darken); saveAs(croppedImageUrl, "cropped-image.jpeg"); } }; const getCroppedAndDarkenedImg = ( image: string | ArrayBuffer, crop: Crop, fileName: string, darken: number ): Promise => { const img = new Image(); img.src = image as string; const scaleX = imageSize < 580 ? img.naturalWidth / (580 * (imageSize / 200)) : img.naturalWidth / 580; const scaleY = img.naturalHeight / 320; const canvas = document.createElement("canvas"); canvas.width = crop.width!; canvas.height = crop.height!; const ctx = canvas.getContext("2d"); if (!ctx) { throw new Error("Canvas context is null"); } ctx.drawImage( img, crop.x! * scaleX, crop.y! * scaleY, crop.width! * scaleX, crop.height! * scaleY, 0, 0, crop.width!, crop.height! ); const imageData = ctx.getImageData(0, 0, crop.width!, crop.height!); const newImageData = imageData.data.map((value, index) => { if ((index + 1) % 4 === 0) { return value; } return value * (1 - darken / 100); }); imageData.data.set(newImageData); ctx.putImageData(imageData, 0, 0); return new Promise((resolve, reject) => { canvas.toBlob((blob) => { if (!blob) { reject(new Error("Canvas is empty")); return; } const file = new File([blob], fileName, { type: "image/jpeg" }); const imageUrl = window.URL.createObjectURL(file); resolve(imageUrl); }, "image/jpeg"); }); }; return ( setCrop(newCrop)} onComplete={onCropComplete}> {src && ( Crop )} {Math.round(crop.width)}x {Math.round(crop.width)} px { setCrop((prevCrop: Crop) => ({ ...prevCrop, unit: "px", x: 210, y: 10, width: 210, height: 300, })); setDarken(0); setImageSize(580); }} style={{ marginBottom: "10px", cursor: "pointer" }} /> Размер setImageSize(newValue as number)} /> Затемнение setDarken(newValue as number)} /> ); };