Skip to content

Commit

Permalink
Merge pull request #212 from mosch/drop-dnd
Browse files Browse the repository at this point in the history
Drop dnd
  • Loading branch information
mosch authored Mar 9, 2018
2 parents b162d1b + a780e97 commit 3272883
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 142 deletions.
10 changes: 2 additions & 8 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
{
"presets": [
"react",
"es2015"
],
"plugins": [
"transform-class-properties",
"transform-object-rest-spread"
]
"presets": ["react", "es2015"],
"plugins": ["transform-class-properties", "transform-object-rest-spread"]
}
80 changes: 50 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@ npm install --save react-avatar-editor

# Usage


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

class MyEditor extends React.Component {
render () {
render() {
return (
<AvatarEditor
image="http://example.com/initialimage.jpg"
Expand All @@ -54,35 +53,33 @@ export default MyEditor
```

## Props
| Prop | Type | Description
| ---------------------- | ---------------- | ---------------
| image | String\|File | The URL of the image to use, or a File (e.g. from a file input).
| width | Number | The total width of the editor.
| height | Number | The total height of the editor.
| border | Number\|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.
| borderRadius | Number | The cropping area border radius.
| color | Number[] | The color of the cropping border, in the form: [red (0-255), green (0-255), blue (0-255), alpha (0.0-1.0)].
| style | Object | Styles for the canvas element.
| scale | Number | The scale of the image. You can use this to add your own resizing slider.
| position | Object | The 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.
| rotate | Number | The rotation degree of the image. You can use this to rotate image (e.g 90, 270 degrees).
| crossOrigin | String | The 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](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for more information.
| disableDrop | Boolean | Disables drop handling behavior (defaults to `false`)
| onDropFile(event) | function | Invoked when user drops a file (or more) onto the canvas. Does not perform any further check.
| onLoadFailure(event) | function | Invoked when an image (whether passed by props or dropped) load fails.
| onLoadSuccess(imgInfo) | function | Invoked when an image (whether passed by props or dropped) load succeeds.
| onImageReady(event) | function | Invoked when the image is painted on the canvas the first time.
| onMouseUp() | function | Invoked when the user releases their mouse button after interacting with the editor.
| onMouseMove(event) | function | Invoked when the user hold and moving the image.
| onImageChange() | function | Invoked when the user changed the image. Not invoked on the first render, and invoked multiple times during drag, etc.
| onPositionChange() | function | Invoked 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.

| Prop | Type | Description |
| ---------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| image | String\|File | The URL of the image to use, or a File (e.g. from a file input). |
| width | Number | The total width of the editor. |
| height | Number | The total height of the editor. |
| border | Number\|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. |
| borderRadius | Number | The cropping area border radius. |
| color | Number[] | The color of the cropping border, in the form: [red (0-255), green (0-255), blue (0-255), alpha (0.0-1.0)]. |
| style | Object | Styles for the canvas element. |
| scale | Number | The scale of the image. You can use this to add your own resizing slider. |
| position | Object | The 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. |
| rotate | Number | The rotation degree of the image. You can use this to rotate image (e.g 90, 270 degrees). |
| crossOrigin | String | The 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](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for more information. |
| onLoadFailure(event) | function | Invoked when an image (whether passed by props or dropped) load fails. |
| onLoadSuccess(imgInfo) | function | Invoked when an image (whether passed by props or dropped) load succeeds. |
| onImageReady(event) | function | Invoked when the image is painted on the canvas the first time. |
| onMouseUp() | function | Invoked when the user releases their mouse button after interacting with the editor. |
| onMouseMove(event) | function | Invoked when the user hold and moving the image. |
| onImageChange() | function | Invoked when the user changed the image. Not invoked on the first render, and invoked multiple times during drag, etc. |
| onPositionChange() | function | Invoked 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. |

## Accessing the resulting image

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


```javascript
import React from 'react'
import AvatarEditor from 'react-avatar-editor'
Expand Down Expand Up @@ -118,21 +115,44 @@ const MyEditor extends React.Component {
export default MyEditor
```

## Adding drag and drop

We recommend using [react-dropzone](https://github.com/react-dropzone/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:

```javascript
class MyEditor extends React.Component {
handleDrop = dropped => {
this.setState({ image: dropped[0] })
}
render() {
return (
<Dropzone
onDrop={this.handleDrop}
disableClick
style={{ width: '250px', height: '250px' }}
>
<ReactAvatarEditor width={250} height={250} image={this.state.image} />
</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``;
`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()``.

like `getImage()`.

# Contributing

For development you can use following build tools:

* `npm run build`: Builds the *minified* dist file: `dist/index.js`
* `npm run watch`: Watches for file changes and builds *unminified* into: `dist/index.js`
* `npm run build`: Builds the _minified_ dist file: `dist/index.js`
* `npm run watch`: Watches for file changes and builds _unminified_ into: `dist/index.js`
* `npm run demo:build`: Builds the demo based on the dist file `dist/index.js`
* `npm run demo:watch`: Run webpack-dev-server. Check demo website [localhost:8080](http://localhost:8080)
63 changes: 38 additions & 25 deletions docs/App.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom'
import ReactAvatarEditor from '../dist/index'

import ReactAvatarEditor from '../src/index'
import Dropzone from 'react-dropzone'
class App extends React.Component {
state = {
image: 'avatar.jpg',
allowZoomOut: false,
position: { x: 0.5, y: 0.5 },
scale: 1,
Expand Down Expand Up @@ -92,30 +93,40 @@ class App extends React.Component {
}

handlePositionChange = position => {
console.log('Position set to', position)
this.setState({ position })
}

handleDrop = acceptedFiles => {
this.setState({ image: acceptedFiles[0] })
}

render () {
return (
<div>
<ReactAvatarEditor
ref={this.setEditorRef}
scale={parseFloat(this.state.scale)}
width={this.state.width}
height={this.state.height}
position={this.state.position}
onPositionChange={this.handlePositionChange}
rotate={parseFloat(this.state.rotate)}
borderRadius={this.state.borderRadius}
onSave={this.handleSave}
onLoadFailure={this.logCallback.bind(this, 'onLoadFailed')}
onLoadSuccess={this.logCallback.bind(this, 'onLoadSuccess')}
onImageReady={this.logCallback.bind(this, 'onImageReady')}
onImageLoad={this.logCallback.bind(this, 'onImageLoad')}
onDropFile={this.logCallback.bind(this, 'onDropFile')}
image={this.state.image || 'avatar.jpg'}
/>
<Dropzone
onDrop={this.handleDrop}
disableClick
style={{ width: '250px', height: '250px' }}
>
<div>
<ReactAvatarEditor
ref={this.setEditorRef}
scale={parseFloat(this.state.scale)}
width={this.state.width}
height={this.state.height}
position={this.state.position}
onPositionChange={this.handlePositionChange}
rotate={parseFloat(this.state.rotate)}
borderRadius={this.state.borderRadius}
onSave={this.handleSave}
onLoadFailure={this.logCallback.bind(this, 'onLoadFailed')}
onLoadSuccess={this.logCallback.bind(this, 'onLoadSuccess')}
onImageReady={this.logCallback.bind(this, 'onImageReady')}
onImageLoad={this.logCallback.bind(this, 'onImageLoad')}
image={this.state.image}
/>
</div>
</Dropzone>
<br />
New File:
<input name='newImage' type='file' onChange={this.handleNewImage} />
Expand Down Expand Up @@ -201,7 +212,7 @@ class App extends React.Component {
<br />
<input type='button' onClick={this.handleSave} value='Preview' />
<br />
{!!this.state.preview &&
{!!this.state.preview && (
<img
src={this.state.preview.img}
style={{
Expand All @@ -212,8 +223,9 @@ class App extends React.Component {
10) *
(this.state.preview.borderRadius / 2 / 100)}px`
}}
/>}
{!!this.state.preview &&
/>
)}
{!!this.state.preview && (
<ImageWithRect
width={
this.state.preview.scale < 1
Expand All @@ -228,7 +240,8 @@ class App extends React.Component {
padding: 5,
border: '1px solid #CCC'
}}
/>}
/>
)}
</div>
)
}
Expand All @@ -244,7 +257,7 @@ class ImageWithRect extends React.Component {
this.redraw()
}

setCanvas = (canvas) => {
setCanvas = canvas => {
if (canvas) this.canvas = canvas
}

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-avatar-editor",
"version": "10.3.0",
"description": "Facebook like avatar / profile picture component. Resize and crop your uploaded image using a intuitive user interface.",
"description": "Avatar / profile picture component. Resize and crop your uploaded image using a intuitive user interface.",
"main": "dist/index.js",
"scripts": {
"clean": "rimraf dist",
Expand All @@ -10,7 +10,7 @@
"lint": "standard --verbose | snazzy",
"test": "jest",
"test:watch": "jest --watch",
"demo:build": "webpack",
"demo:build": "NODE_ENV=production webpack",
"demo:watch": "webpack-dev-server",
"prepublish": "yarn run lint && yarn run test && yarn run clean && yarn run build",
"postversion": "git push --tags origin HEAD"
Expand Down Expand Up @@ -57,6 +57,7 @@
"prop-types": "^15.5.8",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-dropzone": "^4.2.3",
"rimraf": "^2.6.1",
"rollup": "^0.45.2",
"rollup-plugin-babel": "^2.7.1",
Expand Down
8 changes: 1 addition & 7 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import babelrc from 'babelrc-rollup'
import babel from 'rollup-plugin-babel'
import uglify from 'rollup-plugin-uglify'
import _isEqual from 'lodash/isEqual'

const pkg = require('./package.json')
Expand All @@ -18,14 +17,9 @@ config.presets = config.presets.map(([name, config]) => {
}
})

let plugins = [
babel(config),
uglify()
]

export default {
entry: 'src/index.js',
plugins,
plugins: babel(config),
external: external,
globals: {
react: 'React',
Expand Down
Loading

0 comments on commit 3272883

Please sign in to comment.