v4.0.1
What's Changed
- [CI] Split different tests to have better reporting by @raed667 in https://github.com/ricardo-ch/react-easy-crop/pull/317
- Fix Cropper defaultProps types by @cvolant in https://github.com/ricardo-ch/react-easy-crop/pull/323
New Contributors
- @raed667 made their first contribution in https://github.com/ricardo-ch/react-easy-crop/pull/317
- @cvolant made their first contribution in https://github.com/ricardo-ch/react-easy-crop/pull/323
Full Changelog: https://github.com/ricardo-ch/react-easy-crop/compare/v4.0.0...v4.0.1
v4.0.0
🎉
Better rotation handling
🎉
Thanks to an awesome work by @trurl-master, we are now handling rotation properly when computing the output image coordinate.
New initialCroppedAreaPercentages prop
initialCroppedAreaPercentages
is similar to initialCroppedAreaPixels
but more accurate as there is no rounding.
It minimizes the losses of save/restore operations. They're still present on some occasions as the JS floating-point operations accuracy is limited, but it allows to preserve the crop for much longer. initialCroppedAreaPixels
still can be used, but it's a bit risky.
⚠️
Breaking changes
⚠️
TL;DR: If you were not using the rotation
prop, there should be no breaking changes.
The croppedArea
and croppedAreaPixels
output by onCropComplete()
have changed when using the Cropper with a rotation different than 0.
Migration guide
The main impact this major version has is on the croppedAreaPixels
when used together with the rotation. As it now generates bounding box relative values, you will need to remake the part that generates the final image, taking that into account.
Here's an example implementation (codesandbox):
First, calculate the bounding box size:
const image = await createImage(...)
const rotRad = getRadianAngle(rotation)
const bBoxWidth =
Math.abs(Math.cos(rotRad) * image.width) +
Math.abs(Math.sin(rotRad) * image.height)
const bBoxHeight =
Math.abs(Math.sin(rotRad) * image.width) +
Math.abs(Math.cos(rotRad) * image.height)
Second, create a canvas element with the size of the bounding box:
const canvas = document.createElement('canvas')
canvas.width = bBoxWidth
canvas.height = bBoxHeight
Then, rotate the canvas context around the center of the canvas:
const ctx = canvas.getContext('2d')
ctx.translate(bBoxWidth / 2, bBoxHeight / 2)
ctx.rotate(rotRad)
Set context to point to the top-left corner of the rotated image:
ctx.translate(-image.width / 2, -image.height / 2)
Draw the image onto the rotated context:
ctx.drawImage(image, 0, 0)
What you have in the canvas at this point is a rotated image inside its bounding box. Now, you just need to extract the result using croppedAreaPixels
and repaint it on a canvas with the size of the final image:
const data = ctx.getImageData(
croppedAreaPixels.x,
croppedAreaPixels.y,
croppedAreaPixels.width,
croppedAreaPixels.height
)
// set the canvas size to the final image size - this will clear existing context
canvas.width = croppedAreaPixels.width
canvas.height = croppedAreaPixels.height
// paste the extracted image at the top left corner
ctx.putImageData(data, 0, 0)
croppedArea
If you somehow managed to use croppedArea
with rotation before - you're smarter than me. If not - now is the time. The approach is basically the same as with croppedAreaPixels
- you just need to convert percentages to pixels based on the image you're cropping
Here's how you can use percentages server-side and crop using sharp (codesandbox):
Rotate the image:
const image = sharp(...);
await image.rotate(rotation);
Get rotated image bounding box size (basically you need to create a new image out of the rotated one, otherwise the metadata won't change):
const meta = await sharp(await image.toBuffer()).metadata();
Alternatively, you can calculate the bounding box size using the same method we used for the client-side crop
Convert percentages to pixels:
const cropInfo = {
top: Math.round((croppedArea.y / 100) * meta.height),
left: Math.round((croppedArea.x / 100) * meta.width),
width: Math.round((croppedArea.width / 100) * meta.width),
height: Math.round((croppedArea.height / 100) * meta.height)
}
Extract the image:
const myCroppedImage = await image.extract(cropInfo)
Commits
- Change rotated crop area output by @trurl-master in https://github.com/ricardo-ch/react-easy-crop/pull/312
- Update readme video tutorials section by @CodingWith-Adam in https://github.com/ricardo-ch/react-easy-crop/pull/300
- Bump tmpl from 1.0.4 to 1.0.5 by @dependabot in https://github.com/ricardo-ch/react-easy-crop/pull/296
- Bump object-path from 0.11.7 to 0.11.8 in /docs by @dependabot in https://github.com/ricardo-ch/react-easy-crop/pull/295
New Contributors
- @CodingWith-Adam made their first contribution in https://github.com/ricardo-ch/react-easy-crop/pull/300
- @trurl-master made their first contribution in https://github.com/ricardo-ch/react-easy-crop/pull/312
Full Changelog: https://github.com/ricardo-ch/react-easy-crop/compare/v3.5.3...v4.0.0
v3.5.3
- Remove useless preventDefault() e2d3581
- Bump tar from 6.0.5 to 6.1.11 (#286) 34c0756
- Bump tar from 6.0.5 to 6.1.11 in /docs (#287) 8c85319
- Bump object-path from 0.11.5 to 0.11.7 in /docs (#289) a380d4a
https://github.com/ricardo-ch/react-easy-crop/compare/v3.5.2...v3.5.3
v3.5.2
- Refresh video source on component update (#274) ab0ec17
- Bump trim-newlines from 3.0.0 to 3.0.1 (#266) e6e7f11
- Bump ws from 6.2.1 to 6.2.2 (#265) 562d480
https://github.com/ricardo-ch/react-easy-crop/compare/v3.5.1...v3.5.2
v3.5.1
- Add key prop to video source (#260) 102af97
- Update README.md c427986
https://github.com/ricardo-ch/react-easy-crop/compare/v3.5.0...v3.5.1
v3.5.0
- Allow multiple sources for video (#258) aa808fa
- Bump dns-packet from 1.3.1 to 1.3.4 (#256) c79050b
- Bump dns-packet from 1.3.1 to 1.3.4 in /docs (#257) 9691bfa
- Update README.md 4d7fcc8
https://github.com/ricardo-ch/react-easy-crop/compare/v3.4.0...v3.5.0
v3.4.0
New feature
A new property objectFit
is here to let the developer choose how the image/video is adjusted to the parent container.
Possible values are:
contain
: the image will be adjusted to be fully visiblehorizontal-cover
: the image will horizontally fill the croppervertical-cover
: the image will vertically fill the cropper.
Defaults to "contain" (original behavior).
Commits
- Introduce the objectFit property (#236) 4d0bac1
- Bump browserslist from 4.14.5 to 4.16.6 (#252) 989e313
- Bump ssri from 6.0.1 to 6.0.2 (#237) a841e9a
- Bump ssri from 6.0.1 to 6.0.2 in /docs (#238) 78bc79b
- Bump url-parse from 1.4.7 to 1.5.1 (#243) 3528934
- Bump url-parse from 1.4.7 to 1.5.1 in /docs (#244) 2a760f5
- Bump lodash from 4.17.20 to 4.17.21 (#245) c3ca91b
- Bump lodash from 4.17.20 to 4.17.21 in /docs (#246) 3e8db20
- Bump hosted-git-info from 2.8.8 to 2.8.9 (#248) 9dea4cc
- Bump hosted-git-info from 2.8.8 to 2.8.9 in /docs (#249) b309e06
- Bump browserslist from 4.14.5 to 4.16.6 in /docs (#253) a02abba
https://github.com/ricardo-ch/react-easy-crop/compare/v3.3.3...v3.4.0
v3.3.3
- Add Typescript example and use hook for demo b9c18f9
https://github.com/ricardo-ch/react-easy-crop/compare/v3.3.2...v3.3.3
v3.3.2
- Fix: use IE11-compatible way of removing stylesheet 7712fea
- Bump elliptic from 6.5.3 to 6.5.4 (#212) 586669d
- Bump elliptic from 6.5.3 to 6.5.4 in /docs (#213) d682ea6
- Bump socket.io from 2.3.0 to 2.4.1 in /docs (#204) 87a8928
- Bump node-notifier from 8.0.0 to 8.0.1 (#200) b33e3e1
- Bump ini from 1.3.5 to 1.3.7 in /docs (#197) 9c66e00
- Bump ini from 1.3.5 to 1.3.7 (#196) 8ff7142
- Update demo website 7cab395
https://github.com/ricardo-ch/react-easy-crop/compare/v3.3.1...v3.3.2
v3.3.1
- Use normalize-wheel to fix zoom with scroll on Firefox 44b42d6
https://github.com/ricardo-ch/react-easy-crop/compare/v3.3.0...v3.3.1