one-crop-image
v0.1.3
Published
A powerful Angular standalone component for image cropping with advanced features including rotation, mirroring, zoom, aspect ratio presets, drag-and-drop upload, and accessible controls. Export cropped images in PNG, JPEG, or WebP formats with size const
Readme
OneCropImage
A powerful Angular standalone component for image cropping with advanced features including rotation, mirroring, zoom, aspect ratio presets, drag-and-drop upload, and accessible controls. Export cropped images in PNG, JPEG, or WebP formats with size constraints.
Features
- File Upload: Drag-and-drop or click to upload with built-in file input
- Crop Area: Draggable, resizable crop area with visual grid overlay
- Transform Controls: Rotate left/right, mirror horizontal/vertical
- Fine Rotation: Precise rotation slider with tick marks (-45° to 45°)
- Zoom Controls: Zoom in/out with buttons, mouse wheel, or touch gestures
- Aspect Ratio Presets: Free, 1:1, 4:3, 3:4, 16:9, 9:16, 3:2, 2:3
- Interactive Controls: Fit to container, reset crop functionality
- Live Preview: WYSIWYG preview with real-time crop feedback
- Export Options: Multiple formats (PNG, JPEG, WebP) with quality control
- Size Constraints: Max width/height and target file size limits
- Accessibility: ARIA labels, keyboard navigation, focus management
- Theme Support: Built-in light/dark mode with CSS custom properties
- Bootstrap Integration: Compatible with Bootstrap themes
- Responsive Design: Adapts to both vertical and horizontal images
Requirements
- Angular 17+ (Standalone components)
- Modern browsers with Pointer Events and Canvas APIs
- Angular CDK (for focus trap functionality)
Installation
npm install one-crop-image
# or
yarn add one-crop-image
# or
pnpm add one-crop-imageQuickstart
Import the component in your standalone Angular application:
import { Component, signal } from '@angular/core'
import { OneCropImageComponent } from 'one-crop-image'
@Component({
selector: 'app-root',
standalone: true,
imports: [OneCropImageComponent],
template: `
<one-crop-image
[enableRotate]="true"
[enableMirror]="true"
[enableZoom]="true"
[enableFreeRotation]="true"
[outputFormat]="'image/jpeg'"
[outputQuality]="0.9"
[maxOutputWidth]="2048"
[maxOutputHeight]="2048"
[maxBytes]="1024 * 1024"
[emitType]="'both'"
(onImageCroppedAction)="onImageCroppedFile($event)"
(onImageCroppedBase64)="onImageCroppedBase64($event)"
></one-crop-image>
@if (preview(); as src) {
<div class="preview">
<h3>Cropped Result</h3>
<img [src]="src" alt="Cropped image">
</div>
}
`
})
export class AppComponent {
preview = signal<string | null>(null)
onImageCroppedFile(file: File) {
const url = URL.createObjectURL(file)
this.preview.set(url)
}
onImageCroppedBase64(dataUrl: string) {
this.preview.set(dataUrl)
}
}API Reference
Inputs
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| enableRotate | boolean | true | Enable rotation controls |
| enableMirror | boolean | true | Enable mirror/flip controls |
| enableZoom | boolean | true | Enable zoom controls |
| enableFreeRotation | boolean | true | Enable fine rotation slider |
| enableShortcuts | boolean | false | Enable keyboard shortcuts |
| disableDragDrop | boolean | false | Disable drag-and-drop upload |
| disable | boolean | false | Disable all interactions |
| outputFormat | 'image/png' \| 'image/jpeg' \| 'image/webp' | 'image/png' | Output image format |
| outputQuality | number | 0.92 | JPEG/WebP quality (0-1) |
| maxOutputWidth | number? | undefined | Maximum output width in pixels |
| maxOutputHeight | number? | undefined | Maximum output height in pixels |
| maxBytes | number | 1048576 | Target file size in bytes (1MB) |
| emitType | 'file' \| 'base64' \| 'both' | 'file' | Output emission type |
| imageUrl | string \| null | null | Pre-load image from URL |
Outputs
| Event | Type | Description |
|-------|------|-------------|
| onImageCroppedAction | EventEmitter<File> | Emits cropped image as File object |
| onImageCroppedBase64 | EventEmitter<string> | Emits cropped image as base64 data URL |
Example Usage Patterns
Basic Implementation:
<one-crop-image
[enableRotate]="true"
[enableMirror]="true"
[enableZoom]="true"
(onImageCroppedAction)="handleCroppedImage($event)"
></one-crop-image>Advanced Configuration:
<one-crop-image
[enableRotate]="true"
[enableMirror]="true"
[enableZoom]="true"
[enableFreeRotation]="true"
[enableShortcuts]="true"
[outputFormat]="'image/webp'"
[outputQuality]="0.85"
[maxOutputWidth]="1920"
[maxOutputHeight]="1080"
[maxBytes]="512000"
[emitType]="'both'"
(onImageCroppedAction)="saveFile($event)"
(onImageCroppedBase64)="displayPreview($event)"
></one-crop-image>Read-Only Mode:
<one-crop-image
[disable]="true"
[imageUrl]="preloadedImageUrl"
></one-crop-image>Keyboard Shortcuts
When enableShortcuts is true, the following shortcuts are available:
| Shortcut | Action |
|----------|--------|
| + / - | Zoom in/out |
| r / Shift+r | Rotate right/left |
| m / Shift+m | Mirror horizontal/vertical |
| Space + drag | Pan image |
| Arrow keys | Nudge crop area (1px) |
| Shift + Arrow keys | Nudge crop area (10px) |
| Escape | Close modal (always available) |
Theme Customization
The component supports automatic dark mode and Bootstrap theme integration through CSS custom properties:
:root {
--one-accent: #your-brand-color;
--one-bg-primary: #your-background;
--one-text-primary: #your-text-color;
/* ... other custom properties */
}
/* Bootstrap theme support */
[data-bs-theme="dark"] {
--one-bg-primary: #1e293b;
--one-text-primary: #f8fafc;
}Export Behavior
- WYSIWYG Export: The exported image exactly matches what you see in the crop preview
- Format Support: PNG (lossless), JPEG (lossy), WebP (modern, efficient)
- Quality Control: Adjustable quality for JPEG/WebP formats
- Size Constraints: Automatic resizing to fit within specified dimensions
- File Size Target: Best-effort compression to meet target byte size
- Progressive Optimization: Quality reduction and scaling to achieve size goals
Accessibility Features
- Focus Management: Proper focus trapping within the modal
- ARIA Labels: Comprehensive screen reader support
- Keyboard Navigation: Full keyboard accessibility
- High Contrast: Supports system high-contrast modes
- Reduced Motion: Respects
prefers-reduced-motionsettings - Semantic HTML: Proper roles and landmarks
Browser Support
- Chrome/Chromium 80+
- Firefox 75+
- Safari 14+
- Edge 80+
Requires support for Pointer Events, Canvas API, and modern JavaScript features.
Development
Building the Library
ng build one-crop-imageRunning Tests
ng test one-crop-imageLocal Development
ng serveContributing
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes with proper tests
- Ensure all tests pass:
npm test - Submit a pull request
Changelog
v0.1.2
- Enhanced theme support with CSS custom properties
- Improved Bootstrap integration
- Better accessibility features
- Bug fixes and performance improvements
License
MIT License - see LICENSE file for details.
Support
- Issues: GitHub Issues
- Documentation: Full Documentation
- Angular CLI: Angular CLI Documentation
