Code Monkey home page Code Monkey logo

react-easy-crop's Introduction

react-easy-crop

A React component to crop images/videos with easy interactions

version brotli size All Contributors Build Status Test Status MIT License PRs Welcome Auto Release

Demo GIF

react-easy-crop npminsights

Demo

Check out the examples:

Features

  • Supports drag, zoom and rotate interactions
  • Provides crop dimensions as pixels and percentages
  • Supports any images format (JPEG, PNG, even GIF) as url or base 64 string
  • Supports any videos format supported in HTML5
  • Mobile friendly

If react-easy-crop doesn't cover your needs we recommend taking a look at Pintura

Pintura features cropping, rotating, flipping, filtering, annotating, and lots of additional functionality to cover all your image and video editing needs on both mobile and desktop devices.

Learn more about Pintura

Video tutorials from the community

Installation

yarn add react-easy-crop

or

npm install react-easy-crop --save

Basic usage

The Cropper is styled with position: absolute to take the full space of its parent. Thus, you need to wrap it with an element that uses position: relative or the Cropper will fill the whole page.

import { useState, useCallback } from 'react'
import Cropper from 'react-easy-crop'

const Demo = () => {
  const [crop, setCrop] = useState({ x: 0, y: 0 })
  const [zoom, setZoom] = useState(1)

  const onCropComplete = (croppedArea, croppedAreaPixels) => {
    console.log(croppedArea, croppedAreaPixels)
  }

  return (
    <Cropper
      image={yourImage}
      crop={crop}
      zoom={zoom}
      aspect={4 / 3}
      onCropChange={setCrop}
      onCropComplete={onCropComplete}
      onZoomChange={setZoom}
    />
  )
}

Styles

This component requires some styles to be available in the document. By default, you don't need to do anything, the component will automatically inject the required styles in the document head. If you want to disable this behaviour and manually inject the CSS, you can set the disableAutomaticStylesInjection prop to true and use the file available in the package: react-easy-crop/react-easy-crop.css.

Known issues

The cropper size isn't correct when displayed in a modal

If you are using the Cropper inside a modal, you should ensure that there is no opening animation that is changing the modal dimensions (scaling effect). Fading or sliding animations are fine. See #428, #409, #267 or #400 for more details.

Props

Prop Type Required Description
image string The image to be cropped. image or video is required.
video string or Array<{ src: string; type?: string }> The video to be cropped. image or video is required.
crop { x: number, y: number } Position of the media. { x: 0, y: 0 } will center the media under the cropper.
zoom number Zoom of the media between minZoom and maxZoom. Defaults to 1.
rotation number (in degrees) Rotation of the media. Defaults to 0.
aspect number Aspect of the cropper. The value is the ratio between its width and its height. The default value is 4/3
minZoom number Minimum zoom of the media. Defaults to 1.
maxZoom number Maximum zoom of the media. Defaults to 3.
zoomWithScroll boolean Enable zoom by scrolling. Defaults to true
cropShape 'rect' | 'round' Shape of the crop area. Defaults to 'rect'.
cropSize { width: number, height: number } Size of the crop area (in pixels). If you don't provide it, it will be computed automatically using the aspect prop and the media size. You should probably not use this option and should rely on aspect instead. See #186.
showGrid boolean Whether to show or not the grid (third-lines). Defaults to true.
zoomSpeed number Multiplies the value by which the zoom changes. Defaults to 1.
objectFit demo 'contain', 'cover', 'horizontal-cover' or 'vertical-cover' Specifies how the image is shown in the cropper. contain: the image will be adjusted to be fully visible, horizontal-cover: the image will horizontally fill the cropper, vertical-cover: the image will vertically fill the cropper, cover: we automatically pick between horizontal-cover or vertical-cover to have a fully visible image inside the cropper area. Defaults to "contain".
onCropChange crop => void Called every time the crop is changed. Use it to update your crop state.
onZoomChange zoom => void Called every time the zoom is changed. Use it to update your zoom state.
onRotationChange rotation => void Called every time the rotation is changed (with mobile or multi-fingers gestures). Use it to update your rotation state.
onCropSizeChange cropSize => void Called when a change in either the cropSize width or the cropSize height occurs.
onCropComplete Function Called when the user stops moving the media or stops zooming. It will be passed the corresponding cropped area on the media in percentages and pixels (rounded to the nearest integer)
onCropAreaChange Function Very similar to onCropComplete but is triggered for every user interaction instead of waiting for the user to stop.
transform string CSS transform to apply to the image in the editor. Defaults to translate(${crop.x}px, ${crop.y}px) rotate(${rotation}deg) scale(${zoom}) with variables being pulled from props.
style { containerStyle: object, mediaStyle: object, cropAreaStyle: object } Custom styles to be used with the Cropper. Styles passed via the style prop are merged with the defaults.
classes { containerClassName: string, mediaClassName: string, cropAreaClassName: string } Custom class names to be used with the Cropper. Classes passed via the classes prop are merged with the defaults. If you have CSS specificity issues, you should probably use the disableAutomaticStylesInjection prop.
mediaProps object The properties you want to apply to the media tag ( or
restrictPosition boolean Whether the position of the media should be restricted to the boundaries of the cropper. Useful setting in case of zoom < 1 or if the cropper should preserve all media content while forcing a specific aspect ratio for media throughout the application. Example: https://codesandbox.io/s/1rmqky233q.
initialCroppedAreaPercentages { width: number, height: number, x: number, y: number} Use this to set the initial crop position/zoom of the cropper (for example, when editing a previously cropped media). The value should be the same as the croppedArea passed to onCropComplete. This is the preferred way of restoring the previously set crop because croppedAreaPixels is rounded, and when used for restoration, may result in a slight drifting crop/zoom
initialCroppedAreaPixels { width: number, height: number, x: number, y: number} Use this to set the initial crop position/zoom of the cropper (for example, when editing a previously cropped media). The value should be the same as the croppedAreaPixels passed to onCropComplete Example: https://codesandbox.io/s/pmj19vp2yx.
onInteractionStart Function Called every time a user starts a wheel, touch or mousedown event.
onInteractionEnd Function Called every time a user ends a wheel, touch or mousedown event.
onMediaLoaded Function Called when media gets loaded. Gets passed an mediaSize object like { width, height, naturalWidth, naturalHeight }
onTouchRequest (e: React.TouchEvent<HTMLDivElement>) => boolean Can be used to cancel a touch request by returning false.
onWheelRequest (e: WheelEvent) => boolean Can be used to cancel a zoom with wheel request by returning false.
disableAutomaticStylesInjection boolean Whether to auto inject styles using a style tag in the document head on component mount. When disabled you need to import the css file into your application manually (style file is available in react-easy-crop/react-easy-crop.css). Example with sass/scss @import "~react-easy-crop/react-easy-crop";.
setImageRef (ref: React.RefObject<HTMLImageElement>) => void Called when the component mounts, if present. Used to set the value of the image ref object in the parent component.
setVideoRef (ref: React.RefObject<HTMLVideoElement>) => void Called when the component mounts, if present. Used to set the value of the video ref object in the parent component.
setMediaSize (size: MediaSize) => void [Advanced Usage] Used to expose the mediaSize value for use with the getInitialCropFromCroppedAreaPixels and getInitialCropFromCroppedAreaPercentages functions. See this CodeSandbox instance for a simple example.
setCropSize (size: Size) => void [Advanced Usage] Used to expose the cropSize value for use with the getInitialCropFromCroppedAreaPixels and getInitialCropFromCroppedAreaPercentages functions. See this CodeSandbox instance for a simple example.
nonce string The nonce to add to the style tag when the styles are auto injected.

onCropComplete(croppedArea, croppedAreaPixels)

This callback is the one you should use to save the cropped area of the media. It's passed 2 arguments:

  1. croppedArea: coordinates and dimensions of the cropped area in percentage of the media dimension
  2. croppedAreaPixels: coordinates and dimensions of the cropped area in pixels.

Both arguments have the following shape:

const area = {
  x: number, // x/y are the coordinates of the top/left corner of the cropped area
  y: number,
  width: number, // width of the cropped area
  height: number, // height of the cropped area
}

onCropAreaChange(croppedArea, croppedAreaPixels)

This is the exact same callback as onCropComplete, but is triggered for all user interactions. It can be used if you are not performing any render action on it.

  1. croppedArea: coordinates and dimensions of the cropped area in percentage of the media dimension
  2. croppedAreaPixels: coordinates and dimensions of the cropped area in pixels.

Both arguments have the following shape:

const area = {
  x: number, // x/y are the coordinates of the top/left corner of the cropped area
  y: number,
  width: number, // width of the cropped area
  height: number, // height of the cropped area
}

onMediaLoaded(mediaSize)

Called when media gets successfully loaded. This is useful if you want to have a custom zoom/crop strategy based on media size.

Example:

const CONTAINER_HEIGHT = 300

const CroppedImage = ({ image }) => {
  const [crop, onCropChange] = React.useState({ x: 0, y: 0 })
  const [zoom, onZoomChange] = React.useState(1)
  return (
    <Cropper
      image={image}
      crop={crop}
      zoom={zoom}
      onCropChange={onCropChange}
      onZoomChange={onZoomChange}
      onMediaLoaded={(mediaSize) => {
        // Adapt zoom based on media size to fit max height
        onZoomChange(CONTAINER_HEIGHT / mediaSize.naturalHeight)
      }}
    />
  )
}

getInitialCropFromCroppedAreaPercentages(croppedAreaPercentages: Area, mediaSize: MediaSize, rotation: number, cropSize: Size, minZoom: number, maxZoom: number)

[Advanced Usage]

Used to calculate values for crop and zoom based on a desired croppedAreaPercentages value. See this CodeSandbox instance for a simple example.

getInitialCropFromCroppedAreaPixels(croppedAreaPixels: Area, mediaSize: MediaSize, rotation: number, cropSize: Size, minZoom: number, maxZoom: number)

[Advanced Usage]

See getInitialCropFromCroppedAreaPercentages.

Development

yarn
yarn start

Now, open http://localhost:3001/index.html and start hacking!

License

MIT

Maintainers

This project is maintained by Valentin Hervieu.

This project was originally part of @ricardo-ch organisation because I (Valentin) was working at Ricardo. After leaving this company, they gracefully accepted to transfer the project to me. ❤️

Contributors

Thanks goes to these wonderful people (emoji key):


Valentin Hervieu

💬 🐛 💻 📖 💡 🚇 👀 ⚠️ 🔧

Juntae Kim

💻

tafelito

💻

Nicklas

💻

Kyle Poole

💻

Nathaniel Bibler

💻

TheRealSlapshot

💻

Claudiu Andrei

💻

MattyBalaam

💻

Christian Kehr

📖

Christopher Albanese

💻

Benjamin Piouffle

💻

mbalaam

📖

Edouard Short

💻 🤔

All Contributors

🔧

FillPower1

💻

Nihey Takizawa

📖

Alex Lende

🚧

Stefano Ruth

💻 🤔

David Vail

💻

ersefuril

💻

Michal-Sh

💻

Ivan Galiatin

💻 💡

Raed

🚇 📖

cvolant

💻

CodingWith-Adam

📖

LiveBoom

💻

Mateusz Juszczyk

💻

Darren Labithiotis

💻

Oleksii

📖

Vass Bence

📖 💻

Anthony Utt

📖 💻

Sean Parmelee

📖 💻

Glen Davies

💻

carlosdi0

📖

Hüseyin Büyükdere

📖

Pontus Magnusson

💻

kruchkou

💻

Rik

📖

Abdullah Alaqeel

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

react-easy-crop's People

Contributors

ajlende avatar alba-c avatar allcontributors[bot] avatar anotherhermit avatar anthonyutt avatar aqeelat avatar betree avatar bexoss avatar calemon avatar christiankehr avatar claudiuandrei avatar codingwith-adam avatar dependabot[bot] avatar dvail avatar edoudou avatar fillpower1 avatar glendaviesnz avatar huseyinbuyukdere avatar kruchkou avatar labithiotis avatar live-memories-info avatar matixyo avatar mattybalaam avatar mtzalmon avatar nbibler avatar nihey avatar tafelito avatar trurl-master avatar valentinh avatar yokelpole avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-easy-crop's Issues

Your Code has BUG

When I sent in a compressed image, the image didn't show,I checked your code and solved it as follows:
image
image

v2 should re-export types from ./types?

Hi! Big fan on the library. On v2, it's difficult to write down the types for the callbacks because these types

import { Area, MediaSize, Point, Size } from './types';

aren't re-exported from index.d.ts. Let me know if I'm doing something dumb!

Feature Request: onCropChange Event(Live Interaction with preview instead of onCropComplete)

Are you reporting a bug?

  • Please create a CodeSandbox that demonstrates your issue. You can fork the Basic example.

  • Provide the steps to reproduce the issue, e.g.:

    1. Move the image
    2. Resize the window

    Observed behaviour: The cropper is outside the image

    Expected behaviour: The cropper stays within the image

Are you making a feature request?

  • Please describe your use case from user journey point of view, e.g.:

    In my application, when user use the cropper on mobile, I'd like her to be able to zoom without the slider.

  • If you have ideas how to implement your new feature, please share!

  • If you know any examples online that already implement such functionality, please share a link.

Editing an already cropped image

Love the library, thanks for this helpful tool!

How can I set the crop x,y based on an already saved croppedAreaPixels?

Context:
We are getting the croppedAreaPixels coordinates and want to give the user the ability to continue editing an already cropped image. How can we set state crop x,y based on the croppedAreaPixels?

Thanks!

Passing in initialCroppedAreaPixes calls onCropChange

Passing in initialCroppedAreaPixes calls onCropChange

Thanks you so much for this tool. I'm running into an issue when allowing a user to edit an already cropped image. We're passing in the initialCroppedAreaPixels and that is working fine to load the current image. However, both onCropChange and onCropComplete are being called when this happens.

I need to be able to determine actual user interactions from the component being set up with initialCroppedAreaPixels. I was expecting onCropComplete to only run when the user stops zooming or dragging, but it's getting called during the initial setup too.

User Journey:
-User crops an image and is then prompted to save cropped image.
-User opens an already cropped image to continue editing.

expected behavior: user is only prompted to save again, if the user has made a change.
actual behavior: user is prompted to save without have made any changes, because no way to distinguish between user interaction and initial setup.

Errors after dependency upgrades

After https://github.com/ricardo-ch/react-easy-crop/pull/25 was merged I've noticed issues with serverside renders on my application - mainly they do not work correctly when I use react-easy-crop due to a require statement seeking a dependency that is not immediately available.

This is the stacktrace for my error:

 Error: Cannot find module '@emotion/styled-base'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.wrappedResolveFilename [as _resolveFilename] (/data/fe/shared/node_modules/newrelic/lib/shimmer.js:358:39)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Function.wrappedLoad [as _load] (/data/fe/shared/node_modules/newrelic/lib/shimmer.js:364:38)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/data/fe/shared/node_modules/react-easy-crop/dist/styles.js:8:42)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.wrappedLoad [as _load] (/data/fe/shared/node_modules/newrelic/lib/shimmer.js:364:38)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/data/fe/shared/node_modules/react-easy-crop/dist/index.js:12:15)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.wrappedLoad [as _load] (/data/fe/shared/node_modules/newrelic/lib/shimmer.js:364:38)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/data/fe/releases/20190314231140/rendr-fe/shared/react_components/Cropper.react.js:3:23)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.wrappedLoad [as _load] (/data/fe/shared/node_modules/newrelic/lib/shimmer.js:364:38)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/data/fe/releases/20190314231140/rendr-fe/apps/change/app/views/petitions/components/MultiImageUploader.react.js:5:17)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10) code: 'MODULE_NOT_FOUND' }

This is caused by the fully compiled styles.js including the @emotion/styled-base dependency like this:

var _styledBase = _interopRequireDefault(require("@emotion/styled-base"));

This error can also be seen when trying to run the package in runkit: https://npm.runkit.com/react-easy-crop

Get ref to the image element

Hi,
First of all, thanks for your package its really comfortable.
I would like to have an ability to get a ref for the image element (maybe to add a prop imageRef or something similar)
Is it possible?

How to disable mouse wheel ?

I want to remove mouse wheel scrolling for zooming. I just need drag up and down. When I remove zoom, it doesn't zoom but image is moving around outside div. The best way for my need is to remove mouse wheel event.

Order of transformations for back-end service

Hi. I'm trying to replicate what react-easy-crop is doing with the image on my back-end service. I'm wondering in what order the transformations are made, e.g. do you adjust the aspect ratio first, then rotate and then finally crop? I managed to replicate the cropping & zoom fine, but the image always looks offset when I use rotation on my back-end service.

Thanks!

Photo rotation issue on iOS device

Hi, thanks for awesome library! I met the next bug, when you crop a photo in Safari on iOS the output image gets rotated.

https://codesandbox.io/s/react-easy-crop-demo-with-cropped-output-gj6kk

  1. Open this sandbox example in Safari on iPhone
  2. Select a photo
  3. Tap "show img"

Observed behaviour: The output image gets rotated 90 degrees counter-clockwise

Expected behaviour: The output image preserves same orientation as the source image

UPD:

I have found the same issue in another library. And we could use the same solution (ie parse the EXIF data to get image's orientation (the values 1-8), transform the image with a canvas, then use result to initialise the Cropper).

Saving cropped image

Can you tell me how I can save cropped image as blob to upload it to AWS-3 later?

canvas is black in IPhone 8

hi there , tnx for creating this really awesome package

as much as i use this great pkg, i really love i but i had faced with 2 issue for almost in passed five days, every thing is awesome in android phone except:

SAMSUNG A30

only issue is that picture is 90 degree rotated even by using rotation = 0

iPhone 8

just because that iphone tooks pictures around 4k resolution i have an warning in my console in safari that its more than allocated memory to create canvas for that resolution, i think that at the first level it is because of image resolution and at the second its because of the safe area that we create to crop image

there for the canvas (i.e. 1000x1000px) is created , but it is black! and when i', converting it to blob to wire it trough api, it just sends a black image...

please help!

Setting aspect ratio to 1 returns different height & width for croppedAreaPixels

Are you reporting a bug?

  • Demo that shows the issue. I console log the croppedAreaPixels in onCropComplete
    Demo.

  • Provide the steps to reproduce the issue, e.g.:

    1. Set aspect ratio to 1.
    2. Add image
    3. Note how the croppedAreaPixels in onCropComplete have different width and height.

    Observed behaviour: The width and height in croppedAreaPixels are different.

    Expected behaviour: The width and height in croppedAreaPixels should be the same.

Add custom styling

I'd like to add some custom stying to the cropper container, like changing the background colo. Is it possible to add some styling as a prop for the container?

Thanks

zoom out until image very small

is it possible to zoom out to a very small image, so that it can cut all the parts needed ?

Maybe something like this:
image

thanks before, and i really like it. easy to use

Canvas size problem

Are you reporting a bug?

Yes, but it's related to outputting cropped image.

Sandbox Demo

Steps to reproduce:

  1. Just click to show result
  2. Look at console

I think it's related to maximum canvas calculation. I noticed it occurs just after a ctx.translate(safeArea / 2, safeArea / 2);.

I've wondering if there's a another way to get the cropped image without doubling the canvas size. Because if we have current browser limitation about it, how can we enjoy this amazing package (btw, thank you, it's really nice) on current phone which take default pics with 6k~ width and height?

I'm attaching a print of real console error
Screenshot from 2020-03-02 11-56-29
(once sandbox console doesn't describe the exception accurately)

changing aspect state has no effect

open the demo page and change the aspect state using the react dev tools

the cropper should update its gutter according to the new aspect ratio, but it does not, the gutter does not change.

How to avoid breaking out of boundaries by zooming out?

I have a square crop size of 256 px and need to make sure that the image covers the whole square. Therefore I want to achieve two things:

  1. Start with a zoom level high enough to cover the crop area
  2. Set the minZoom dynamically so that the user can't zoom out so far that the square isn't covered anymore

Is there an easy way to do it? Maybe a working example?

I've attached a screenshot of the behaviour I want to avoid.
Screenshot 2019-10-06 at 17 50 58

Massive image size increase after cropping

Hey,

what's the reason for the massive increase in some pictures after cropping it?

For example, one picture has ~2MB and after cropping it with its full size it has ~20MB. In our use case, we limit the size of uploaded pics on the client and server-side. This random behavior makes it had to check the size property as the user uploads a pic correctly but then gets an error that the image is too big.

Best,
sutefan

Add Typescript types to package

It would be nice to have Typescript types for the component embedded in the package itself.

I created this snippet by reviewing the documentation and looking at the implementation and use it in my project as a .d.ts file but I have no experience in creating and testing npm packages so I’ll leave that to someone else if possible.

declare namespace Cropper {
  interface Crop {
    x: number;
    y: number;
  }
  interface CropSize {
    width: number;
    height: number;
  }
  type CropArea = Crop & CropSize;
  interface CropperProps {
    /**
     * The image to be cropped.
     **/
    image: string;
    /**
     * Position of the image. { x: 0, y: 0 } will center the image under the cropper.
     **/
    crop: Crop;
    /**
     * Zoom of the image between minZoom and maxZoom. Defaults to 1.
     **/
    zoom?: number;
    /**
     * Rotation of the image. Defaults to 0.
     **/
    rotation?: number;
    /**
     * Aspect of the cropper. The value is the ratio between its width and its height.
     * The default value is 4/3
     **/
    aspect?: number;
    /**
     * Minimum zoom of the image. Defaults to 1.
     **/
    minZoom?: number;
    /**
     * Maximum zoom of the image. Defaults to 3.
     **/
    maxZoom?: number;
    /**
     * Shape of the crop area. Defaults to 'rect'.
     **/
    cropShape?: "rect" | "round";
    /**
     * Size of the crop area (in pixels).
     * If you don't provide it, it will be computed automatically using the aspect prop and the image size.
     * Warning: this cannot be changed once the component is displayed.
     * If you need to change it (based on some user inputs for instance),
     * you can force the component to be reset by using a key.
     **/
    cropSize?: CropSize;
    /**
     * Whether to show or not the grid (third-lines). Defaults to true.
     **/
    showGrid?: boolean;
    /**
     * Multiplies the value by which the zoom changes. Defaults to 1.
     **/
    zoomSpeed?: number;
    /**
     * Allows setting the crossOrigin attribute on the image.
     **/
    crossOrigin?: string;
    /**
     * Called everytime the crop is changed. Use it to update your crop state.
     **/
    onCropChange: (crop: Crop) => void;
    /**
     * Called everytime the zoom is changed. Use it to update your zoom state.
     **/
    onZoomChange?: (zoom: number) => void;
    /**
     * Called everytime the rotation is changed (with mobile gestures).
     * Use it to update your rotation state.
     **/
    onRotationChange?: (rotation: number) => void;
    /**
     * Called when the user stops moving the image or stops zooming.
     * It will be passed the corresponding cropped area on the image in percentages and pixels
     **/
    onCropComplete?: (
      croppedArea: CropArea,
      croppedAreaPixels: CropArea
    ) => void;
    /**
     * Called when error occurs while loading an external image
     **/
    onImgError?: (event: React.ReactEventHandler<HTMLImageElement>) => void;
    /**
     * Custom styles to be used with the Cropper.
     * Styles passed via the style prop are merged with the defaults.
     **/
    style?: {
      containerStyle?: React.CSSProperties;
      imageStyle?: React.CSSProperties;
      cropAreaStyle?: React.CSSProperties;
    };
    /**
     * Custom class names to be used with the Cropper.
     * Classes passed via the classes prop are merged with the defaults.
     **/
    classes?: {
      containerClassName?: string;
      imageClassName?: string;
      cropAreaClassName?: string;
    };
    /**
     * Whether the position of the image should be restricted to the boundaries of the cropper.
     * Useful setting in case of zoom < 1 or if the cropper should preserve all image content
     * while forcing a specific aspect ratio for image throughout the application.
     * Example: https://codesandbox.io/s/1rmqky233q.
     **/
    restrictPosition?: boolean;
    /**
     * Use this to set the initial crop position/zoom of the cropper
     * (for example, when editing a previously cropped image).
     * The value should be the same as the croppedAreaPixelspassed to
     * onCropComplete Example: https://codesandbox.io/s/pmj19vp2yx.
     **/
    initialCroppedAreaPixels?: CropArea;
    /**
     * Called everytime a user starts a wheel, touch or mousedown event.
     **/
    onInteractionStart?: () => void;
    /**
     * Called everytime a user ends a wheel, touch or mousedown event.
     **/
    onInteractionEnd?: () => void;
  }
}

declare class Cropper extends React.Component<Cropper.CropperProps> {}

declare module "react-easy-crop" {
  export default Cropper;
}

save the images

Are you reporting a bug?

  • Please create a CodeSandbox that demonstrates your issue. You can fork the Basic example.

  • Provide the steps to reproduce the issue, e.g.:

    1. Move the image
    2. Resize the window

    Observed behaviour: The cropper is outside the image

    Expected behaviour: The cropper stays within the image

Are you making a feature request?

  • Please describe your use case from user journey point of view, e.g.:

    In my application, when user use the cropper on mobile, I'd like her to be able to zoom without the slider.

  • If you have ideas how to implement your new feature, please share!

  • If you know any examples online that already implement such functionality, please share a link.

Crop mask is too small for vertical images

If an image is very tall, it seems to want to fit the image inside the canvas by shrinking the crop mask. I would like the mask to remain bigger, and the image to be outside the canvas viewport until the user zooms out. Is that possible?

I'm using restrictPosition={false} and minZoom={0.9}.

Here's how it looks when the image is loaded:

image

and after zooming in:

image

Material UI Button variant type warning in example

Are you reporting a bug?

  • Please create a CodeSandbox that demonstrates your issue. You can fork the Basic example.

    I have checked all examples and it seems like only the following is affected:
    Example with output of the cropped image

  • Provide the steps to reproduce the issue, e.g.:

    1. Open the console in codesandbox (in webapp, not F12)

    Observed behaviour: Warning: Failed prop type: Material-UI: the raised variant will be removed in the next major release. contained is equivalent and should be used instead.

    Expected behaviour: No warning in console.

Should be a quick fix by just replacing variant="raised" with variant="contained" for the <Button /> component.

setting cropSize affects restoration from initialCroppedAreaPixels

it appears that the calculations done to restore the cropper's inner state from a previously saved Area (passed in through initialCroppedAreaPixels) are affected by passing in a fixed cropSize.

  • example. note that this is a fork of the demo from the readme "Example with crop saved/loaded to/from local storage", with the addition of one extra prop

    cropSize={{ width: 400, height: 400 }}
  • Provide the steps to reproduce the issue, e.g.:

    1. Move the image so that the crop box appears at the top left ({x: 0, y: 0}):
      Screen Shot 2019-11-23 at 1 03 02 PM

    2. Reload the page
      Screen Shot 2019-11-23 at 1 03 16 PM

    Observed behaviour: The cropper is no longer located at {x: 0, y: 0}

    Expected behaviour: The cropper is still located at {x: 0, y: 0}

Bug when trying to crop SVG on Mozilla

Bug when trying to crop SVG on Mozilla

Use the crop on a SVG image using Firefox (didn't identify the exact condition right now, I'm on a fixed div for what it's worth).

Observed behaviour: In OnImageLoaded callback parameter, imageSize.naturalHeight and imageSize.naturalWidth is equal 0.

Expected behaviour: In OnImageLoaded callback parameter, imageSize.naturalHeight and imageSize.naturalWidth is equal to the natural size of svg.

Right now, it is not a pain point for me as I have found a solution to work around it.
How ever, the bug did not occurred when trying it on codesandbox, so it might be the case only in a specific case that I did not identify yet.

Here is my attempt to reproduce the bug, so you have more info of what I was trying to do. https://codesandbox.io/s/react-easy-crop-demo-nw5es

Just wanted you to know it might be an issue for someone else, if you want to close the issue now I'll understand.

Cant resolve 'fs' in blah blah blh

Are you reporting a bug?

yes

  • Provide the steps to reproduce the issue, e.g.:

    1. installed the pkg npm install react-easy-crop
    2. removed the node_modules folder and lock file
    3. npm install
    4. in your build you will fail and get this error
      xxxxxxxxxxxxxxxxx

Are you making a feature request?

this is my webpack build failing error:


WARNING in ./node_modules/express/lib/view.js 81:13-25
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/js/v2.0__components/UploadImage/UploadImage.jsx
 @ ./src/js/routes.js
 @ ./src/js/v1.0__components/App.jsx
 @ ./src/js/Index.jsx

ERROR in ./node_modules/destroy/index.js
Module not found: Error: Can't resolve 'fs' in '/home/amdev/Projects/02_snappfood_vms/node_modules/destroy'
 @ ./node_modules/destroy/index.js 14:17-30
 @ ./node_modules/send/index.js
 @ ./node_modules/express/lib/utils.js
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/js/v2.0__components/UploadImage/UploadImage.jsx
 @ ./src/js/routes.js
 @ ./src/js/v1.0__components/App.jsx
 @ ./src/js/Index.jsx

ERROR in ./node_modules/etag/index.js
Module not found: Error: Can't resolve 'fs' in '/home/amdev/Projects/02_snappfood_vms/node_modules/etag'
 @ ./node_modules/etag/index.js 22:12-25
 @ ./node_modules/express/lib/utils.js
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/js/v2.0__components/UploadImage/UploadImage.jsx
 @ ./src/js/routes.js
 @ ./src/js/v1.0__components/App.jsx
 @ ./src/js/Index.jsx

ERROR in ./node_modules/express/lib/view.js
Module not found: Error: Can't resolve 'fs' in '/home/amdev/Projects/02_snappfood_vms/node_modules/express/lib'
 @ ./node_modules/express/lib/view.js 18:9-22
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/js/v2.0__components/UploadImage/UploadImage.jsx
 @ ./src/js/routes.js
 @ ./src/js/v1.0__components/App.jsx
 @ ./src/js/Index.jsx

ERROR in ./node_modules/mime/mime.js
Module not found: Error: Can't resolve 'fs' in '/home/amdev/Projects/02_snappfood_vms/node_modules/mime'
 @ ./node_modules/mime/mime.js 2:9-22
 @ ./node_modules/send/index.js
 @ ./node_modules/express/lib/utils.js
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/js/v2.0__components/UploadImage/UploadImage.jsx
 @ ./src/js/routes.js
 @ ./src/js/v1.0__components/App.jsx
 @ ./src/js/Index.jsx

ERROR in ./node_modules/send/index.js
Module not found: Error: Can't resolve 'fs' in '/home/amdev/Projects/02_snappfood_vms/node_modules/send'
 @ ./node_modules/send/index.js 23:9-22
 @ ./node_modules/express/lib/utils.js
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/js/v2.0__components/UploadImage/UploadImage.jsx
 @ ./src/js/routes.js
 @ ./src/js/v1.0__components/App.jsx
 @ ./src/js/Index.jsx

ERROR in ./node_modules/express/lib/request.js
Module not found: Error: Can't resolve 'net' in '/home/amdev/Projects/02_snappfood_vms/node_modules/express/lib'
 @ ./node_modules/express/lib/request.js 18:11-25
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/js/v2.0__components/UploadImage/UploadImage.jsx
 @ ./src/js/routes.js
 @ ./src/js/v1.0__components/App.jsx
 @ ./src/js/Index.jsx

what can i do ???
please help...

Prevent zoom by scroll

Hi,
I would like to prevent changing the zoom by scrolling because in my case it's disturbing the page scrolling.
Does there is support for such an option or do you any idea for me to implement it?
Thanks
BTW, I really like this package 😍 .

Circular crop

Are you making a feature request?

  • Please describe your use case from user journey point of view, e.g.:

Our app (like many others) "fake crop" people profile images to be circular using the css border-radius properties. This works fine on the web but not so much in desktop email clients - here’s a listing I found.

Because of that I'm searching for a cropper that allows me to crop by a circle rather than a square or rectangle. I found a JQuery component - Croppie but wrapping it in React or rewriting it seemed like too much work.

This component seems well written and maintained so I was curious how hard it would be to add a feature that crops the image by a circle instead of a square?

I understand that rules out JPEG as an output format since there’s no accepted standard for including an alpha mask.

If you could provide some pointers I’d be happy to try modifying the code myself.

Feature: custom cropShape prop

Can we have custom crop shape passed in through cropShape prop?

  • Potential idea for implementing it (to add extra option for cropShape prop, css class or styleObject) :
    Screen Shot 2019-12-05 at 10 40 09 PM

  • square has custom css called 'css-nikas5'
    Screen Shot 2019-12-05 at 10 19 43 PM

  • circle has custom css called 'css-5xmhn'
    Screen Shot 2019-12-05 at 10 20 20 PM

  • I have been using your library in my app for client. The client would like to have a heart shape crop. Thought it would be a nice feature to have if possible

FeatureRequest - customisable zoom range.

In my application I am working on the maximum zoom amount on an image so that it maps to 1pixel in source image at the maximum zoom.

I have noticed that if this value over 3 then I cannot use the scrollwheel to go beyond this point - although a range slider can break this maximum.

Ideally the component would use default props to set a minimum and maximum range and these could be overridden as required.

Hi!

Are you reporting a bug?

  • Please create a CodeSandbox that demonstrates your issue. You can fork the Basic example.

  • Provide the steps to reproduce the issue, e.g.:

    1. Move the image
    2. Resize the window

    Observed behaviour: The cropper is outside the image

    Expected behaviour: The cropper stays within the image

Are you making a feature request?

  • Please describe your use case from user journey point of view, e.g.:

    In my application, when user use the cropper on mobile, I'd like her to be able to zoom without the slider.

  • If you have ideas how to implement your new feature, please share!

  • If you know any examples online that already implement such functionality, please share a link.

Ability to fit max cropSize width

I am working on an image cropper component for a banner and react-easy-crop so far keeps its promise, it's working great and is damn easy to implement -- thanks for making it happen!

I am currently facing a small issue: when the zoom is not defined yet, I would need the image to fit the full width instead of the full height.

Here's a screencast to help visualize the issue

Peek 26-08-2019 14-47

Proposed solution

From my understanding, the line responsible for this is https://github.com/ricardo-ch/react-easy-crop/blob/ff9300a82dc28718921c7a825e137b8f58c35b31/src/helpers.js#L138

I'd like to introduce a new prop:

  • Name: initialFit
  • Type: Can be "width" or "height" (defaults to height to preserve the current behaviour).
  • Description: If set to "width", the initial zoom will be set to match the full width of the container. If set to "height", the image will fit the height of the container. Default to "height".

If maintainers are ok with this, I'd be happy to make a PR to make it happen.

Crop output can be wrong

Demo: https://codesandbox.io/s/q8q1mnr01w

  1. Zoom the image
  2. Move it to the top right
  3. Unzoom image quickly
  4. show the output

Observed behaviour: There is a black bar on the right

Expected behaviour: The output matches the cropped area

image

This is because the output is computed before the crop value has been restricted and updated in the state.

Output of cropArea does not make sense for zooms smaller than 1 if restrictPosition is false

Are you reporting a bug?

  • Please create a CodeSandbox that demonstrates your issue. You can fork the Basic example.

    Fork of Example with output of the cropped image

    Note: I have also modified the getCroppedImg function.

  • Provide the steps to reproduce the issue, e.g.:

    1. Click on Show image

    Observed behaviour: The image is zoomed in. The zoom is clearly >=1 and the cropped image does not have a white border as expected.

    Expected behaviour: If the position is not restricted and the zoom is smaller than 1, the cropArea and cropAreaPixels is calculated correctly and allows cropArea sizes bigger than the maximum image dimensions.

I have looked at the source code and it seems like the limitArea function is doing the trick here. If I understand the function correctly, we should not use it if the zoom is smaller than 1 and if restrictPosition={false}, because it will not allow the cropArea to be bigger than the image. However, I am not sure if I understand the function correctly in the context of setCalculatedCrop.

Is there a way to apply draggable crop re-sizing

We need a way to enable users to crop images via a select/drag style (a.k.a free form cropping). Currently looks like the library has a fixed crop size specification property.

This means if crop size is not provided, we can still auto compute the crop size however provide a free form (re-size) cropping ability for the user.

Here is a library that provides that free form cropping ability by default
https://github.com/DominicTobias/react-image-crop

any thoughts?

issue with using in the modal

hello. I need to use it in the modal. but in this case I cant move the image for some reason. it works after resizing browser's window though.

Can't get Image to resize

Can't scale the image inside a div, it always has to take up the full screen?? Any ways around this

Feature Request: Make mouse-wheel zoom-speed configurable

We would like to adjust the speed with which a mouse-wheel-turn zooms in or out of the image.

Maybe the value would be a specific step-value, by which the zoom will be increased/decreased or speed-factor, by which the mouse-wheel-delta will be multiplied, with 1 being the default and current behaviour.

Libraries implementing such a feature:

iphone image exif orientation

With pictures uploaded from iphone, there's exif data specifying the orientation of the image. It seems this data is not preserved after cropping the image. Are there any solutions to this?

Moving images with zoom smaller than 1 not possible

Are you reporting a bug?

  • Please create a CodeSandbox that demonstrates your issue. You can fork the Basic example.

    https://codesandbox.io/s/92r5r56zqr?fontsize=14

  • Provide the steps to reproduce the issue, e.g.:

    1. Try to move the image

    Observed behaviour: It is not possible to move the image within the cropping boundaries if the zoom is smaller than 1.

    Expected behaviour: Zooms smaller than 1 should be supported in order to not only crop, but also change the aspect ratio of an image. In my application I'd like to get images with a constant aspect ratio. For the best UX I'd like the user to be able to also just use any image with a white background. Vertical images are especially a problem. A possible implementation could be to modify the restrictPosition function. I do a lot of JS myself, but if you have a quick fix for this it would be great to see this improvement to this overall very nice project!

Module resolution problems in examples

Are you reporting a bug?

  • Please create a CodeSandbox that demonstrates your issue. You can fork the Basic example.

    Basic example

  • Provide the steps to reproduce the issue, e.g.:

    1. Run the example in codesandbox
    2. Wait for transpilation to finish

    Observed behaviour: ModuleNotFoundError
    Could not find module in path: '@babel/runtime/helpers/builtin/interopRequireDefault' relative to '/node_modules/@material-ui/lab/Slider/index.js'

    Expected behaviour: The example renders correctly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.