import ActiveObjectContext from '@/components/Context/activeObject/ObjectContext'; import CanvasContext from '@/components/Context/canvasContext/CanvasContext'; import { useContext, useRef, useState } from 'react'; import { Button } from '@/components/ui/button'; import { fabric } from 'fabric'; import Resizer from "react-image-file-resizer"; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Slider } from '@/components/ui/slider'; import { HardDriveUpload, ImagePlus, Upload, Crop, RotateCw, FileType, ChevronUp, ChevronDown } from 'lucide-react'; import { Card, CardContent } from '@/components/ui/card'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import CollapsibleComponent from './CollapsibleComponent'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; const features = [ { icon: Upload, title: 'Auto-Resize', description: 'Images larger than 1080px are automatically resized' }, { icon: Crop, title: 'Custom Dimensions', description: 'Set your preferred resize dimensions' }, { icon: RotateCw, title: 'Quality & Rotation', description: 'Adjust image quality and rotation as needed' }, { icon: FileType, title: 'Format Conversion', description: 'Convert between various image formats' }, ] const AddImageIntoShape = () => { const { canvas } = useContext(CanvasContext); const { activeObject, setActiveObject } = useContext(ActiveObjectContext); const [errorMessage, setErrorMessage] = useState(""); const [width, setWidth] = useState(1080); const [height, setHeight] = useState(1080); const [quality, setQuality] = useState(100); const [rotation, setRotation] = useState("0"); const [format, setFormat] = useState('JPEG'); const fileInputRef = useRef(null); const [isOpen, setIsOpen] = useState(false); const handleResize = (file, callback) => { Resizer.imageFileResizer( file, width, height, format, quality, parseInt(rotation), (resizedFile) => { callback(resizedFile); // Pass the resized file to the callback }, 'file' // Output type ); }; const fileHandler = (e) => { const file = e.target.files[0]; if (!file) { setErrorMessage("No file selected."); return; } // Check if the file is an SVG if (file.type === "image/svg+xml") { // Add SVG directly to canvas without compression const blobUrl = URL.createObjectURL(file); const imgElement = new Image(); imgElement.src = blobUrl; imgElement.onload = () => { handleImageInsert(imgElement); // Insert the image without resizing URL.revokeObjectURL(blobUrl); clearFileInput(); }; imgElement.onerror = () => { console.error("Failed to load SVG."); setErrorMessage("Failed to load SVG."); URL.revokeObjectURL(blobUrl); clearFileInput(); }; return; } // Handle raster images (JPEG, PNG, etc.) const imgElement = new Image(); const blobUrl = URL.createObjectURL(file); imgElement.src = blobUrl; imgElement.onload = () => { // If the width is greater than 1080px, compress the image if (imgElement.width > 1080) { handleResize(file, (compressedFile) => { const compressedBlobUrl = URL.createObjectURL(compressedFile); const compressedImg = new Image(); compressedImg.src = compressedBlobUrl; compressedImg.onload = () => { handleImageInsert(compressedImg); // Insert the resized image URL.revokeObjectURL(compressedBlobUrl); // Clean up clearFileInput(); }; compressedImg.onerror = () => { console.error("Failed to load compressed image."); setErrorMessage("Failed to load compressed image."); URL.revokeObjectURL(compressedBlobUrl); clearFileInput(); }; }); } else { handleImageInsert(imgElement); // Insert the original image if no resizing needed clearFileInput(); } URL.revokeObjectURL(blobUrl); // Clean up clearFileInput(); }; imgElement.onerror = () => { console.error("Failed to load image."); setErrorMessage("Failed to load image."); URL.revokeObjectURL(blobUrl); clearFileInput(); }; }; const clearFileInput = () => { if (fileInputRef.current) { fileInputRef.current.value = ""; } }; const handleImageInsert = (img) => { if (!activeObject) { setErrorMessage("No active object selected!"); return; } // Ensure absolute positioning for the clipPath activeObject.set({ isClipPath: true, // Custom property absolutePositioned: true, }); // Calculate scale factors based on clip object size let scaleX = activeObject.width / img.width; let scaleY = activeObject.height / img.height; if (activeObject?.width < 100) { scaleX = 0.2; } if (activeObject.height < 100) { scaleY = 0.2; } // Create a fabric image object with scaling and clipPath const fabricImage = new fabric.Image(img, { scaleX: scaleX, scaleY: scaleY, left: activeObject.left, top: activeObject.top, clipPath: activeObject, // Apply clipPath to the image originX: activeObject.originX, // Match origin point originY: activeObject.originY // Match origin point }); // Adjust position based on the clipPath's transformations fabricImage.set({ left: activeObject.left, top: activeObject.top, angle: activeObject.angle // Match rotation if any }); canvas.add(fabricImage); canvas.setActiveObject(fabricImage); setActiveObject(fabricImage); canvas.renderAll(); }; // canvas.remove(activeObject); const content = () => { return (
{/* Image Insertion

Insert and customize images within shapes. Adjust image position and clipping after insertion.

Key Features:

{features.map((feature, index) => (

{feature.title}

{feature.description}

))}
*/} Image Insertion

Insert and customize images within shapes. Adjust image position and clipping after insertion.

{features.map((feature, index) => (

{feature.title}

{feature.description}

))}
{errorMessage && (

{errorMessage}

)}
{/* Width Slider */}
setWidth(value[0])} />
{/* Height Slider */}
setHeight(value[0])} />
{/* Quality Slider */} { format === "JPEG" &&
setQuality(value[0])} />
}
{/* Rotation */}
{/* Format Dropdown */}
) } return ( {content()} ); }; export default AddImageIntoShape;