Cropped output
Use croppedAreaPixels to render the selected part of the image.
Loading example...
Code
import { useState } from 'react'
import Cropper, { type Area, type Point } from 'react-easy-crop'
type OutputExampleProps = {
image: string
}
export default function OutputExample({ image }: OutputExampleProps) {
const [crop, setCrop] = useState<Point>({ x: 0, y: 0 })
const [zoom, setZoom] = useState(1)
const [rotation, setRotation] = useState(0)
const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null)
const [croppedImage, setCroppedImage] = useState<string | null>(null)
function onCropComplete(_: Area, croppedPixels: Area) {
setCroppedAreaPixels(croppedPixels)
}
async function showCroppedImage() {
if (!croppedAreaPixels) {
return
}
setCroppedImage(await getCroppedImg(image, croppedAreaPixels, rotation))
}
return (
<>
<div className="cropper">
<Cropper
image={image}
crop={crop}
zoom={zoom}
rotation={rotation}
aspect={4 / 3}
onCropChange={setCrop}
onCropComplete={onCropComplete}
onRotationChange={setRotation}
onZoomChange={setZoom}
/>
</div>
<button onClick={showCroppedImage}>Show cropped image</button>
{croppedImage ? <img src={croppedImage} alt="Cropped result" /> : null}
</>
)
}
async function getCroppedImg(
imageSrc: string,
pixelCrop: Area,
rotation = 0,
flip = { horizontal: false, vertical: false }
) {
const image = await createImage(imageSrc)
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if (!ctx) {
return null
}
const rotRad = getRadianAngle(rotation)
const { width: bBoxWidth, height: bBoxHeight } = rotateSize(image.width, image.height, rotation)
canvas.width = bBoxWidth
canvas.height = bBoxHeight
ctx.translate(bBoxWidth / 2, bBoxHeight / 2)
ctx.rotate(rotRad)
ctx.scale(flip.horizontal ? -1 : 1, flip.vertical ? -1 : 1)
ctx.translate(-image.width / 2, -image.height / 2)
ctx.drawImage(image, 0, 0)
const croppedCanvas = document.createElement('canvas')
const croppedCtx = croppedCanvas.getContext('2d')
if (!croppedCtx) {
return null
}
croppedCanvas.width = pixelCrop.width
croppedCanvas.height = pixelCrop.height
croppedCtx.drawImage(
canvas,
pixelCrop.x,
pixelCrop.y,
pixelCrop.width,
pixelCrop.height,
0,
0,
pixelCrop.width,
pixelCrop.height
)
return new Promise<string | null>((resolve) => {
croppedCanvas.toBlob((file) => {
resolve(file ? URL.createObjectURL(file) : null)
}, 'image/jpeg')
})
}
function getRadianAngle(degreeValue: number) {
return (degreeValue * Math.PI) / 180
}
function rotateSize(width: number, height: number, rotation: number) {
const rotRad = getRadianAngle(rotation)
return {
width: Math.abs(Math.cos(rotRad) * width) + Math.abs(Math.sin(rotRad) * height),
height: Math.abs(Math.sin(rotRad) * width) + Math.abs(Math.cos(rotRad) * height),
}
}
function createImage(url: string) {
return new Promise<HTMLImageElement>((resolve, reject) => {
const image = new Image()
image.addEventListener('load', () => resolve(image))
image.addEventListener('error', reject)
image.setAttribute('crossOrigin', 'anonymous')
image.src = url
})
}