import React, { FC, useEffect, 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, useMediaQuery, useTheme, } from "@mui/material"; import quiz from "../../assets/quiz-template-6.png"; import { ResetIcon } from "@icons/ResetIcon"; interface Iprops { opened: boolean; onClose: () => void; picture?: string | ArrayBuffer; } export const CroppingModal: FC = ({ opened, onClose, picture }) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(786)); const style = { position: "absolute" as "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", width: isMobile ? "343px" : "620px", bgcolor: "background.paper", boxShadow: 24, padding: "20px", borderRadius: "8px", }; const styleSlider = { width: isMobile ? "350px" : "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`, }, }, }; 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); console.log(src); useEffect(() => { if (picture) { setSrc(picture); } }, [picture]); 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; let scaleX = 360 / 580; let scaleY = 219 / 320; if (img.naturalWidth) { scaleX = img.naturalWidth / 580; } if (img.naturalHeight) { scaleY = img.naturalHeight / 320; } console.log(scaleX); console.log(scaleY); 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)} /> ); };