Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
YouTube Security Videosheise & c't: Gebrauchte CPU gekauft – plötzlich ist der PC gesperrt(01.10.2026 um 13:08 Uhr)
•
Windows Tipps & SecuritySD-Karten sind teuer wie nie: So halten sie deutlich länger(01.10.2026 um 13:15 Uhr)
•••••••••
YouTube Security Videosheise & c't: Gebrauchte CPU gekauft – plötzlich ist der PC gesperrt(01.10.2026 um 13:08 Uhr)
•
Windows Tipps & SecuritySD-Karten sind teuer wie nie: So halten sie deutlich länger(01.10.2026 um 13:15 Uhr)
•••••••••
Intelligence View
⚡ tsecurity.de Intelligence

Building a Modern Image Cropper in React with CropperJS 2.x

Image cropping is a common requirement in web applications - from profile picture uploads to photo editing tools. While CropperJS has been the go-to library…

Beitrag
0
Seite
0
↗ Quelle (dev.to)
Social ReaktionenReagiere als Erste:r — dein Feedback zählt!

Image cropping is a common requirement in web applications - from profile picture uploads to photo editing tools. While CropperJS has been the go-to library for years, version 2.x brought a complete rewrite using modern web components. This created a gap: the existing react-cropper library only supports v1.x.



In this tutorial, I'll show you how to implement image cropping in React using CropperJS 2.x with full TypeScript support.






Why CropperJS 2.x?



CropperJS 2.x is a ground-up rewrite that leverages modern web standards:




  • ✅ Web Components - Built on native Custom Elements

  • ✅ Better Performance - Optimized rendering and memory usage

  • ✅ Modern Architecture - Cleaner API surface

  • ✅ Framework Agnostic - Works anywhere web components work



However, using web components directly in React requires careful handling of refs, events, and lifecycle management.






Meet react-cropper-2



I built @imerljak/react-cropper-2 to provide idiomatic React bindings for CropperJS 2.x. The library offers three flexible APIs:





  1. Component API - Drop-in React component (easiest)


  2. Hook API - Composable hook with render function


  3. Advanced Hook API - Maximum control for power users



All with full TypeScript support.






Installation






npm install @imerljak/react-cropper-2 cropperjs@2






The library automatically imports and registers CropperJS web components, so you don't need to do it manually.






Quick Start: Component API



The simplest way to get started is using the <Cropper> component:




import { useRef } from 'react';
import { Cropper, type CropperRef } from '@imerljak/react-cropper-2';

function ProfilePicture() {
const cropperRef = useRef<CropperRef>(null);

const handleSave = async () => {
const canvas = await cropperRef.current?.getCroppedCanvas();
if (canvas) {
const blob = await new Promise(resolve =>
canvas.toBlob(resolve, 'image/jpeg', 0.9)
);
// Upload blob to your server
console.log('Ready to upload:', blob);
}
};

return (
<div>
<Cropper
ref={cropperRef}
src="/profile-photo.jpg"
alt="Profile picture"
aspectRatio={1} // Square crop
onReady={() => console.log('Cropper ready!')}
onChange={(e) => console.log('Crop changed:', e.detail.bounds)}
/>
<button onClick={handleSave}>Save</button>
<button onClick={() => cropperRef.current?.reset()}>Reset</button>
</div>
);
}









Live Preview with useCropper Hook



For more control, use the useCropper hook which provides built-in state management:




import { useState } from 'react';
import { useCropper } from '@imerljak/react-cropper-2';

function ImageEditor() {
const [previewUrl, setPreviewUrl] = useState<string>();

const { renderCropper, bounds, reset, getCroppedCanvas } = useCropper({
src: '/my-image.jpg',
alt: 'Edit me',
aspectRatio: 16 / 9,
onChange: async () => {
// Update preview on every crop change
const canvas = await getCroppedCanvas();
setPreviewUrl(canvas?.toDataURL('image/png'));
},
});

return (
<div className="editor-layout">
<div className="cropper-section">
{renderCropper({ style: { maxHeight: '500px' } })}
</div>

<div className="preview-section">
<h3>Preview</h3>
{previewUrl && <img src={previewUrl} alt="Preview" />}
{bounds && (
<pre>
{JSON.stringify(bounds, null, 2)}
</pre>
)}
<button onClick={reset}>Reset</button>
</div>
</div>
);
}









Advanced: Custom Cropper UI



Need complete control? Use useCropperAdvanced to build custom UIs:




import { useCropperAdvanced } from '@imerljak/react-cropper-2';

function CustomCropper() {
const {
canvasRef,
selectionRef,
bounds,
setBounds,
reset,
} = useCropperAdvanced({
autoInitialize: true,
onReady: () => console.log('Ready!'),
});

const setSquareCrop = () => {
setBounds({ x: 50, y: 50, width: 300, height: 300 });
};

return (
<div>
<cropper-canvas ref={canvasRef} background>
<cropper-image
src="/image.jpg"
alt="Custom cropper"
rotatable
scalable
/>
<cropper-selection
ref={selectionRef}
initial-coverage={0.8}
movable
resizable
outlined
>
<cropper-grid role="grid" bordered covered />
<cropper-handle action="move" />
<cropper-handle action="n-resize" />
<cropper-handle action="e-resize" />
<cropper-handle action="s-resize" />
<cropper-handle action="w-resize" />
<cropper-handle action="ne-resize" />
<cropper-handle action="nw-resize" />
<cropper-handle action="se-resize" />
<cropper-handle action="sw-resize" />
</cropper-selection>
</cropper-canvas>

<div className="custom-controls">
<button onClick={setSquareCrop}>Square Crop</button>
<button onClick={reset}>Reset</button>
{bounds && (
<span>
{bounds.width}x{bounds.height}
</span>
)}
</div>
</div>
);
}









TypeScript Benefits



The library is TypeScript-first with comprehensive type definitions:




import type {
CropperRef,
CropperBounds,
CropperEventHandler,
GetCroppedCanvasOptions
} from '@imerljak/react-cropper-2';

// Fully typed ref
const cropperRef = useRef<CropperRef>(null);

// Type-safe event handlers
const handleChange: CropperEventHandler = (event) => {
const { bounds, canvas } = event.detail;
console.log(`Crop: ${bounds.width}x${bounds.height}`);
};

// Type-safe options
const options: GetCroppedCanvasOptions = {
width: 800,
height: 600,
fillColor: '#fff',
};









Common Use Cases






Avatar Upload with Circular Crop






function AvatarUpload() {
const cropperRef = useRef<CropperRef>(null);

const handleUpload = async () => {
const canvas = await cropperRef.current?.getCroppedCanvas({
width: 200,
height: 200,
});

if (canvas) {
const blob = await new Promise<Blob | null>(resolve =>
canvas.toBlob(resolve, 'image/jpeg', 0.95)
);

const formData = new FormData();
formData.append('avatar', blob!, 'avatar.jpg');

await fetch('/api/upload-avatar', {
method: 'POST',
body: formData,
});
}
};

return (
<Cropper
ref={cropperRef}
src="/uploaded-photo.jpg"
aspectRatio={1}
initialCoverage={0.8}
rounded // Makes it appear circular
/>
);
}









Multiple Aspect Ratios






function MultiAspectCropper() {
const [aspectRatio, setAspectRatio] = useState(16 / 9);

return (
<div>
<div className="aspect-ratio-controls">
<button onClick={() => setAspectRatio(16 / 9)}>16:9</button>
<button onClick={() => setAspectRatio(4 / 3)}>4:3</button>
<button onClick={() => setAspectRatio(1)}>1:1</button>
<button onClick={() => setAspectRatio(undefined)}>Free</button>
</div>

<Cropper
src="/image.jpg"
aspectRatio={aspectRatio}
/>
</div>
);
}









CORS Image Handling



When cropping images from different domains:




<Cropper
src="https://example.com/image.jpg"
crossOrigin="anonymous"
alt="Remote image"
/>









API Overview






Component Props




































































Prop Type Default Description
src string required Image URL
aspectRatio number - Aspect ratio (e.g., 16/9)
initialCoverage number 0.5 Initial crop coverage (0-1)
background boolean true Show background
movable boolean true Allow moving selection
resizable boolean true Allow resizing
zoomable boolean true Allow zooming
onReady function - Fires when ready
onChange function - Fires on crop change





Ref Methods






interface CropperRef {
getCanvas: () => CropperCanvasElement | null;
getBounds: () => CropperBounds | null;
setBounds: (bounds: Partial<CropperBounds>) => void;
reset: () => void;
clear: () => void;
getCroppedCanvas: (options?) => Promise<HTMLCanvasElement | null>;
}









Live Examples



Check out the interactive Storybook documentation with live examples covering:




  • Basic cropping scenarios

  • Different aspect ratios

  • Custom styling

  • Event handling patterns

  • All three API approaches

  • Advanced configurations






Browser Support



Works in all modern browsers that support:




  • ES2020

  • Web Components (Custom Elements)

  • ES Modules






Comparison with react-cropper (v1)



If you're coming from react-cropper (v1.x wrapper):











































Feature react-cropper react-cropper-2
CropperJS version 1.x 2.x
Architecture jQuery-based Web Components
TypeScript Partial Full, strict mode
React 19 ❌ ✅
Bundle size Larger Smaller
APIs 1 (component) 3 (component + hooks)





When to Use Each API





  • Component API - Quick integration, simple use cases, prefer components


  • Hook API - Need state management, composable logic, custom layouts


  • Advanced Hook API - Complete control, custom UI, complex interactions






Wrapping Up



react-cropper-2 brings CropperJS 2.x's modern web component architecture to React with three flexible APIs, full TypeScript support, and comprehensive testing.






Resources





Try it in your next React project and let me know what you think! Questions and feedback are always welcome.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Building a Modern Image Cropper in React with CropperJS 2.x

Thematisch verwandte Begriffe: Building, Modern, Image, Cropper · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag