-
-
Notifications
You must be signed in to change notification settings - Fork 230
feat: add image cropper #2738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat: add image cropper #2738
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: a1c1bd2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 80 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Image Cropper
Overview
This PR introduces a new Image Cropper machine component to the Zag.js library. The image cropper is a comprehensive, headless state machine that provides full-featured image cropping functionality with support for zoom, rotation, flipping, precise crop area manipulation, and image export capabilities.
Features
Core Functionality
Interaction Methods
Advanced Features
Architecture
File Structure
image-cropper.anatomy.ts
: Defines component parts (root, viewport, image, selection, handle)image-cropper.machine.ts
: Core state machine with 3 states (idle, dragging, panning) and comprehensive action handlersimage-cropper.connect.ts
: API layer connecting machine to DOM with event handlers, prop getters, and image export functionalityimage-cropper.types.ts
: TypeScript interfaces and types for props, API, state, and export optionsimage-cropper.utils.ts
: Utility functions for crop calculations, resizing, and offset clampingimage-cropper.props.ts
: Property definitions and split props utilityimage-cropper.dom.ts
: DOM element ID and accessor utilitiesState Machine
The machine operates in three states:
Key Algorithms
Configuration Options
Size & Constraints
minWidth
,minHeight
: Minimum crop dimensions (default: 40px)maxWidth
,maxHeight
: Maximum crop dimensions (default: Infinity)aspectRatio
: Optional fixed aspect ratio (width/height)initialCrop
: Custom initial crop rectangleZoom & Transform
defaultZoom
: Initial zoom level (default: 1)minZoom
,maxZoom
: Zoom range (default: 1-5)zoomStep
: Increment per wheel step (default: 0.1)zoomSensitivity
: Pinch gesture responsiveness (default: 2)defaultRotation
: Initial rotation in degrees (default: 0)defaultFlip
: Initial flip state (default: no flip)Behavior
cropShape
: "rectangle" or "circle" (default: "rectangle")fixedCropArea
: Lock crop position/size while panning image (default: false)nudgeStep
,nudgeStepShift
,nudgeStepCtrl
: Keyboard movement incrementsCallbacks
onZoomChange
: Fired when zoom level changesonRotationChange
: Fired when rotation changesonFlipChange
: Fired when flip state changesonCropChange
: Fired when the crop area changesAPI Methods
The
ImageCropperApi
provides:setZoom(zoom)
: Set zoom level programmaticallysetRotation(rotation)
: Set rotation in degreessetFlip(flip)
: Set flip stateflipHorizontally(value?)
: Toggle or set horizontal flipflipVertically(value?)
: Toggle or set vertical flipresize(handlePosition, delta)
: Resize crop area from a handlegetCroppedImage(options?)
: Export the cropped image with all transformations appliedtype
(image format),quality
(0-1),output
("blob" or "dataUrl")getRootProps()
,getViewportProps()
,getImageProps()
,getSelectionProps()
,getHandleProps()
: Prop getters for DOM elementsImage Export
The
getCroppedImage
method provides powerful export capabilities:The export functionality:
crossOrigin="anonymous"
on image element)Accessibility
Testing
Comprehensive E2E tests included in
e2e/image-cropper.e2e.ts
with test model ine2e/models/image-cropper.model.ts
.Demo
The example implementation in
examples/next-ts/pages/image-cropper.tsx
showcases all features including: