feat(cropper): expand image export API
This commit is contained in:
@@ -9,6 +9,8 @@ toc:
|
||||
title: Geometry functions
|
||||
- id: export
|
||||
title: Exporting an image
|
||||
- id: api
|
||||
title: API
|
||||
- id: cross-origin
|
||||
title: Cross-origin images
|
||||
---
|
||||
@@ -34,6 +36,27 @@ const [value, setValue] = React.useState({ x: 0, y: 0, zoom: 1 })
|
||||
|
||||
## Exporting an image {#export}
|
||||
|
||||
The shortest path exports the current result through the component ref:
|
||||
|
||||
```tsx
|
||||
import { Cropper, type CropperHandle } from "@workspace/cropper"
|
||||
|
||||
const cropperRef = React.useRef<CropperHandle>(null)
|
||||
|
||||
const result = await cropperRef.current?.getCropImage({
|
||||
outputType: "base64",
|
||||
type: "image/jpeg",
|
||||
quality: 0.9,
|
||||
width: 1200,
|
||||
})
|
||||
|
||||
<Cropper ref={cropperRef} src={src} />
|
||||
```
|
||||
|
||||
`getCropImage()` returns `undefined` until the image is ready. `outputType` defaults to `"blob"`; `"base64"` returns a data URL suitable for previews or form values. Quality must be between `0` and `1`.
|
||||
|
||||
Use the pure function when no component instance is available:
|
||||
|
||||
```tsx
|
||||
const blob = await cropImage(src, area, {
|
||||
type: "image/webp",
|
||||
@@ -42,7 +65,24 @@ const blob = await cropImage(src, area, {
|
||||
})
|
||||
```
|
||||
|
||||
Supplying only `width` or `height` preserves the crop aspect ratio. `shape: "circle"` clips through an ellipse; provide `background` when an opaque JPEG background is required.
|
||||
Supplying only `width` or `height` preserves the crop aspect ratio. `shape: "circle"` clips through an ellipse; provide `background` when an opaque JPEG background is required. `getCropImage(source, area, options)` is the corresponding pure function for Blob/base64 output.
|
||||
|
||||
## API {#api}
|
||||
|
||||
| Prop | Type | Description |
|
||||
| ------------------------------ | ----------------------------------- | ------------------------------------------------ |
|
||||
| `src` | `string \| Blob` | An image URL, Blob, or File. |
|
||||
| `aspectRatio` | `number \| \`${number}:${number}\`` | Crop viewport ratio; defaults to `1`. |
|
||||
| `width` / `height` | matching `CSSProperties` value | Optional inline container dimensions. |
|
||||
| `value` / `defaultValue` | `CropperValue` | Controlled or uncontrolled translation and zoom. |
|
||||
| `minZoom` / `maxZoom` | `number` | Zoom range; defaults to `1` through `4`. |
|
||||
| `shape` | `"rectangle" \| "circle"` | Viewport shape. |
|
||||
| `showGrid` | `boolean` | Whether to render the rule-of-thirds grid. |
|
||||
| `onCropAreaChange` | `(area) => void` | Runs when the valid source-image crop changes. |
|
||||
| `onCropComplete` | `(area, value) => void` | Runs after an interaction or reset completes. |
|
||||
| `onImageLoad` / `onImageError` | callbacks | Observe image loading state. |
|
||||
|
||||
`CropperHandle` exposes `element`, `getCropArea()`, `getCropImage(options)`, and `reset()`. Use `rootRef` when a raw DOM ref is needed; the component `ref` is reserved for the imperative handle.
|
||||
|
||||
## Cross-origin images {#cross-origin}
|
||||
|
||||
|
||||
@@ -10,31 +10,25 @@ toc:
|
||||
## Example {#example}
|
||||
|
||||
```tsx
|
||||
import { Cropper, cropImage, type CropArea } from "@workspace/cropper"
|
||||
import { Cropper, type CropperHandle } from "@workspace/cropper"
|
||||
|
||||
function AvatarCropper({ src }: { src: string }) {
|
||||
const [area, setArea] = React.useState<CropArea>()
|
||||
const cropperRef = React.useRef<CropperHandle>(null)
|
||||
|
||||
async function saveAvatar() {
|
||||
if (!area) return
|
||||
const blob = await cropImage(src, area, {
|
||||
const blob = await cropperRef.current?.getCropImage({
|
||||
height: 512,
|
||||
shape: "circle",
|
||||
type: "image/png",
|
||||
width: 512,
|
||||
})
|
||||
await uploadAvatar(blob)
|
||||
if (blob instanceof Blob) await uploadAvatar(blob)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Cropper
|
||||
src={src}
|
||||
shape="circle"
|
||||
className="size-72"
|
||||
onCropAreaChange={setArea}
|
||||
/>
|
||||
<button type="button" disabled={!area} onClick={saveAvatar}>
|
||||
<Cropper ref={cropperRef} src={src} shape="circle" className="size-72" />
|
||||
<button type="button" onClick={saveAvatar}>
|
||||
Save avatar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@ Add the package source to the application's Tailwind stylesheet:
|
||||
|
||||
## Cropper {#cropper}
|
||||
|
||||
Give the component an explicit width; `aspectRatio` determines its height:
|
||||
Use classes or pass `width` and `height` directly. `aspectRatio` accepts a number or a `"width:height"` string:
|
||||
|
||||
```tsx
|
||||
import { Cropper, type CropArea } from "@workspace/cropper"
|
||||
@@ -33,7 +33,7 @@ function ProductImageCropper({ src }: { src: string }) {
|
||||
<Cropper
|
||||
src={src}
|
||||
alt="Product"
|
||||
aspectRatio={4 / 3}
|
||||
aspectRatio="4:3"
|
||||
className="w-full max-w-xl rounded-xl"
|
||||
onCropAreaChange={setArea}
|
||||
/>
|
||||
@@ -43,6 +43,8 @@ function ProductImageCropper({ src }: { src: string }) {
|
||||
|
||||
Users can drag the image, scroll to zoom, or focus the Cropper and use the arrow, `+`, `-`, `0`, and `Home` keys.
|
||||
|
||||
`src` can also be a `Blob` or `File` from a file picker. The component creates a temporary object URL and revokes it when the source changes or the component unmounts.
|
||||
|
||||
## External controls {#controls}
|
||||
|
||||
Control the crop with `value` and `onValueChange` to connect a Slider or reset button. `minZoom` is clamped to at least `1`, ensuring that the image always covers the viewport.
|
||||
Control the crop with `value` and `onValueChange` to connect a Slider. For a quick reset, call `reset()` on the component ref. `minZoom` is clamped to at least `1`, ensuring that the image always covers the viewport.
|
||||
|
||||
@@ -21,9 +21,12 @@ toc:
|
||||
- Pinch, wheel, double-click, and keyboard zooming.
|
||||
- Controlled and uncontrolled state.
|
||||
- Rectangular and circular viewports.
|
||||
- Numeric and `"width:height"` viewport ratios.
|
||||
- URL and local `Blob` image sources with automatic object URL cleanup.
|
||||
- Resize-aware image constraints.
|
||||
- Standalone pure geometry functions.
|
||||
- Canvas export to PNG, JPEG, or WebP Blob.
|
||||
- Imperative reset, crop-area access, and export through a component ref.
|
||||
- Canvas export to PNG, JPEG, or WebP Blob/base64 output.
|
||||
|
||||
## Data model {#data-model}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user