skip to Main Content

I want code dropzone with image cropper
I want when i upload image first it will open modal of cropper and after that final cropped image will saved. Create one component and use that component every wherever needed. In next js using typescript

2

Answers


  1. Chosen as BEST ANSWER
    import React, { useRef, useState, useCallback, ReactNode } from "react";
    import { useDropzone } from 'react-dropzone';
    import Cropper, { ReactCropperElement } from "react-cropper";
    import "cropperjs/dist/cropper.css";
    
    const DropzoneWithCropper: React.FC = () => {
    const [src, setSrc] = useState<string | null>(null);
    const [croppedImage, setCroppedImage] = useState<string | null>(null);
    const [showModal, setShowModal] = useState<boolean>(false);
    const cropperRef = useRef<ReactCropperElement>(null);
    
    const onDrop = useCallback((acceptedFiles: File[]) => {
        setCroppedImage(null);
        const file = acceptedFiles[0];
        const reader = new FileReader();
        reader.onload = () => {
            setSrc(reader.result as string);
        };
        reader.readAsDataURL(file);
        setShowModal(true);
    }, []);
    
    const onCrop = useCallback(() => {
        const cropper = cropperRef.current?.cropper;
        if (cropper) {
            setCroppedImage(cropper.getCroppedCanvas().toDataURL());
        }
    }, []);
    
    const { getRootProps, getInputProps } = useDropzone({
        onDrop,
        multiple: false,
        accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg'] },
    });
    
    const closeModal = () => {
        setShowModal(false);
        setSrc(null)
        setCroppedImage(null)
    };
    const cropComplete = () => {
        setShowModal(false);
    };
    
    return (
        <div>
            <div {...getRootProps({ className: 'dropzone' })}>
                <input {...getInputProps()} />
                {croppedImage ? (
                    <div className="image-preview">
                        <img src={croppedImage} alt="Cropped Preview" />
                    </div>
                ) : (
                    <p>{src ? "Drag the crop area or resize it to crop the image" : "Drag 'n' drop an image here, or click to select one"}</p>
                )}
            </div>
    
            <Modal showModal={showModal} onClose={closeModal}>
                <Cropper
                    src={src}
                    style={{ height: 400, width: "100%" }}
                    initialAspectRatio={16 / 9}
                    guides={false}
                    crop={onCrop}
                    ref={cropperRef}
                />
                <button type="button" onClick={cropComplete}>Crop</button>
            </Modal>
        </div>
    
    );
    };
    interface ModalProps {
    showModal: boolean;
    onClose: () => void;
    children: ReactNode; // Specify children as 
    ReactNode
    }
    const Modal: React.FC<ModalProps> = ({ 
    showModal, onClose, children }) => {
    if (!showModal) return null;
    return (
        <div className="modal">
            <div className="modal-content">
                {children}
                <button onClick= 
      {onClose}>Close</button>
            </div>
        </div>
    );
    };
    
    export default DropzoneWithCropper;
    

  2. import React, { useState } from 'react';
    import Dropzone from 'react-dropzone';
    import Cropper from 'react-cropper';
    import 'cropperjs/dist/cropper.css';
    
    interface ImageUploaderWithCropperProps {
      onSave: (croppedImage: string) => void;
    }
    
    const ImageUploaderWithCropper: React.FC<ImageUploaderWithCropperProps> = ({ onSave }) => {
      const [image, setImage] = useState<string | null>(null);
      const [croppedImage, setCroppedImage] = useState<string | null>(null);
      const [cropper, setCropper] = useState<Cropper | null>(null);
    
      const onDrop = (acceptedFiles: File[]) => {
        const reader = new FileReader();
        reader.onload = () => {
          setImage(reader.result as string);
        };
        reader.readAsDataURL(acceptedFiles[0]);
      };
    
      const handleCrop = () => {
        if (cropper) {
          const croppedImageUrl = cropper.getCroppedCanvas().toDataURL();
          setCroppedImage(croppedImageUrl);
          onSave(croppedImageUrl);
        }
      };
    
      return (
        <div>
          <Dropzone onDrop={onDrop} accept="image/*" multiple={false}>
            {({ getRootProps, getInputProps }) => (
              <section>
                <div {...getRootProps()} style={{ border: '1px dashed black', padding: '20px', textAlign: 'center' }}>
                  <input {...getInputProps()} />
                  <p>Drag 'n' drop an image here, or click to select an image</p>
                </div>
              </section>
            )}
          </Dropzone>
          {image && (
            <div>
              <Cropper
                src={image}
                style={{ height: 400, width: '100%' }}
                aspectRatio={1}
                guides={true}
                crop={handleCrop}
                onInitialized={(instance) => {
                  setCropper(instance);
                }}
              />
            </div>
          )}
        </div>
      );
    };
    
    export default ImageUploaderWithCropper;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search