Home

Awesome

react-avatar-editor

<a href="https://www.npmjs.com/package/react-avatar-editor"><img alt="npm version" src="https://badge.fury.io/js/react-avatar-editor.svg"></a> <a href="https://npmjs.org/package/react-avatar-editor"><img alt="Downloads" src="http://img.shields.io/npm/dm/react-avatar-editor.svg"></a> Build Status Design

Avatar / profile picture cropping component (like on Facebook). Resize, crop and rotate your uploaded image using a simple and clean user interface.

Features

Install

Just use your favorite package manager to add react-avatar-editor to your project:

yarn add react-avatar-editor

npm i --save react-avatar-editor

pnpm add react-avatar-editor

Demo

Usage

import React from 'react'
import AvatarEditor from 'react-avatar-editor'

const MyEditor = () => {
  return (
    <AvatarEditor
      image="http://example.com/initialimage.jpg"
      width={250}
      height={250}
      border={50}
      color={[255, 255, 255, 0.6]} // RGBA
      scale={1.2}
      rotate={0}
    />
  )
}

export default MyEditor

Props

PropTypeDescription
imageString|FileThe URL of the image to use, or a File (e.g. from a file input).
widthNumberThe total width of the editor.
heightNumberThe total height of the editor.
borderNumber|Number[]The cropping border. Image will be visible through the border, but cut off in the resulting image. Treated as horizontal and vertical borders when passed an array.
borderRadiusNumberThe cropping area border radius.
colorNumber[]The color of the cropping border, in the form: [red (0-255), green (0-255), blue (0-255), alpha (0.0-1.0)].
backgroundColorStringThe background color of the image if it's transparent.
styleObjectStyles for the canvas element.
scaleNumberThe scale of the image. You can use this to add your own resizing slider.
positionObjectThe x and y co-ordinates (in the range 0 to 1) of the center of the cropping area of the image. Note that if you set this prop, you will need to keep it up to date via onPositionChange in order for panning to continue working.
rotateNumberThe rotation degree of the image. You can use this to rotate image (e.g 90, 270 degrees).
crossOriginStringThe value to use for the crossOrigin property of the image, if loaded from a non-data URL. Valid values are "anonymous" and "use-credentials". See this page for more information.
classNameString|String[]className property passed to the canvas element
onLoadFailure(event)functionInvoked when an image (whether passed by props or dropped) load fails.
onLoadSuccess(imgInfo)functionInvoked when an image (whether passed by props or dropped) load succeeds.
onImageReady(event)functionInvoked when the image is painted on the canvas the first time.
onMouseUp()functionInvoked when the user releases their mouse button after interacting with the editor.
onMouseMove(event)functionInvoked when the user hold and moving the image.
onImageChange()functionInvoked when the user changed the image. Not invoked on the first render, and invoked multiple times during drag, etc.
onPositionChange()functionInvoked when the user pans the editor to change the selected area of the image. Passed a position object in the form { x: 0.5, y: 0.5 } where x and y are the relative x and y coordinates of the center of the selected area.
disableBoundaryChecksBooleanSet to true to allow the image to be moved outside the cropping boundary.
disableHiDPIScalingBooleanSet to true to disable devicePixelRatio based canvas scaling. Can improve performance of very large canvases on mobile devices.

Accessing the resulting image

The resulting image will have the same resolution as the original image, for that you can use getImage, regardless of the editor's size. If you want the image sized in the dimensions of the canvas you can use getImageScaledToCanvas.

import React, { useRef } from 'react'
import AvatarEditor from 'react-avatar-editor'

const MyEditor = () => {
  const editor = useRef(null);

  render() {
    return (
      <div>
        <AvatarEditor
          ref={editor}
          image="http://example.com/initialimage.jpg"
          width={250}
          height={250}
          border={50}
          scale={1.2}
        />
        <button onClick={() => {
          if (this.editor) {
            // This returns a HTMLCanvasElement, it can be made into a data URL or a blob,
            // drawn on another canvas, or added to the DOM.
            const canvas = editor.current.getImage()

            // If you want the image resized to the canvas size (also a HTMLCanvasElement)
            const canvasScaled = editor.current.getImageScaledToCanvas()
          }
        }}>Save</button>
      </div>
    )
  }
}

export default MyEditor

Adding drag and drop

We recommend using react-dropzone. It allows you to add drag and drop support to anything really easy. Here is an example how to use it with react-avatar-editor:

import React, { useState } from 'react'
import AvatarEditor from 'react-avatar-editor'
import Dropzone from 'react-dropzone'

const MyEditor = () => {
  const [image, setImage] = useState('http://example.com/initialimage.jpg')

  return (
    <Dropzone
      onDrop={(dropped) => setImage(dropped[0])}
      noClick
      noKeyboard
      style={{ width: '250px', height: '250px' }}
    >
      {({ getRootProps, getInputProps }) => (
        <div {...getRootProps()}>
          <AvatarEditor width={250} height={250} image={image} />
          <input {...getInputProps()} />
        </div>
      )}
    </Dropzone>
  )
}

Accessing the cropping rectangle

Sometimes you will need to get the cropping rectangle (the coordinates of the area of the image to keep), for example in case you intend to perform the actual cropping server-side.

getCroppingRect() returns an object with four properties: x, y, width and height; all relative to the image size (that is, comprised between 0 and 1). It is a method of AvatarEditor elements, like getImage().

Note that: getImage() returns a canvas element and if you want to use it in src attribute of img, convert it into a blob url.

const getImageUrl = async () => {
  const dataUrl = editor.current.getImage().toDataURL()
  const res = await fetch(dataUrl)
  const blob = await res.blob()

  return window.URL.createObjectURL(blob)
}

// Usage
const imageURL = await getImageUrl()

<img src={imageURL} ... />

Contributing

For development you can use following build tools:

Kudos

Kudos and thanks to dan-lee for the work & many contributions to this project! Also oyeanuj, mtlewis and hu9o and all other awesome people contributing to this in any way.