Skip to content
This repository was archived by the owner on Dec 20, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,19 @@ ReactDOM.render(

## Props

| Prop | Description | Type | Default |
| ----------- | ------------------------------------------------------------ | ---------------------------------------- | ------- |
| src | Src of background image. | string | - |
| coordinates | An array of coordinate( see the table blew), {id, x, y, width, height}. | array | [] |
| width | Width of background image. | number(in pixel) | - |
| height | Height of background image. | number(in pixel) | - |
| onDraw | A callback which hanppends when a user starts drawing a new rectangle. | funtion(coordinate , index, coordinates) | - |
| onDrag | A callback which hanppends when a user stars draging a exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onResize | A callback which hanppends when a user starts resizing a exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onChange | A callback which hanppends when a user starts drawing, draging or resizing a new/exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onDelete | A callback which hanppends when a user delete a exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onLoad | The callback is triggered when the background image is loaded. | onLoad(e) | - |
| Prop | Description | Type | Default |
| ----------------- | ------------------------------------------------------------ | ---------------------------------------- | ------- |
| src | Src of background image. | string | - |
| coordinates | An array of coordinate( see the table blew), {id, x, y, width, height}. | array | [] |
| width | Width of background image. | number(in pixel) | - |
| height | Height of background image. | number(in pixel) | - |
| onDraw | A callback which hanppends when a user starts drawing a new rectangle. | funtion(coordinate , index, coordinates) | - |
| onDrag | A callback which hanppends when a user stars draging a exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onResize | A callback which hanppends when a user starts resizing a exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onChange | A callback which hanppends when a user starts drawing, draging or resizing a new/exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onDelete | A callback which hanppends when a user delete a exited rectangle. | funtion(coordinate , index, coordinates) | - |
| onLoad | The callback is triggered when the background image is loaded. | onLoad(e) | - |
| permitAreaOverlap | If set to false prevent the overlap between crop areas | boolean | true |


### coordinate
Expand Down
1 change: 1 addition & 0 deletions examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class App extends React.Component {
// onDraw={this.changeCoordinate}
onChange={this.changeCoordinate}
onDelete={this.deleteCoordinate}
permitAreaOverlap={false}
// onLoad={e => console.log(e.target.height, e.target.width)}
/>
</div>
Expand Down
63 changes: 58 additions & 5 deletions src/components/Crop.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { equals, is, update, remove } from 'ramda'
import interact from 'interactjs'
import { DeleteIcon, NumberIcon } from './Icons'

import { areaNotAvailable } from '../utils'

class Crop extends Component {
static cropStyle = (coordinate) => {
const {
x, y, width, height,
x, y, width, height, background, zIndex,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will output some internal data to user

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these properties is need for the functionality:

  • z-index allow to work to current box event
  • background to set a red color to see what happens.

all these properties are temporary

} = coordinate

return {
Expand All @@ -19,10 +21,9 @@ class Crop extends Component {
height,
top: y,
left: x,


zIndex: zIndex || 0,
boxShadow: '0 0 6px #000',
background: '#8c8c8c',
background: background || '#8c8c8c',
opacity: 0.6,
}
}
Expand All @@ -35,6 +36,8 @@ class Crop extends Component {
left: true, right: true, bottom: true, top: true,
},
})
.on('mousedown', this.handleMouseDown)
.on('mouseup', this.handleMouseUp)
.on('dragmove', this.handleDragMove)
.on('resizemove', this.handleResizeMove)
}
Expand All @@ -44,6 +47,35 @@ class Crop extends Component {
|| (nextProps.index !== this.props.index)
}

handleMouseDown = () => {
const { index, coordinate } = this.props
this.previus = {
index,
coordinate,
}
}

handleMouseUp = () => {
const {
coordinate, coordinates, onResize, onChange, permitAreaOverlap,
} = this.props

if (!permitAreaOverlap) {
if (coordinate.background && this.previus) {
const nextCoordinates = update(this.previus.index, this.previus.coordinate)(coordinates)
if (is(Function, onResize)) {
onResize(this.previus.coordinate, this.previus.index, nextCoordinates)
}
if (is(Function, onChange)) {
onChange(this.previus.coordinate, this.previus.index, nextCoordinates)
}
}
}
coordinate.zIndex = undefined
this.previus = undefined
}


handleResizeMove = (e) => {
const {
index,
Expand All @@ -52,13 +84,22 @@ class Crop extends Component {
coordinates,
onResize,
onChange,
permitAreaOverlap,
} = this.props
const { width, height } = e.rect
const { left, top } = e.deltaRect

const nextCoordinate = {
...coordinate, x: x + left, y: y + top, width, height,
}

if (!permitAreaOverlap && areaNotAvailable(coordinates, coordinate)) {
nextCoordinate.background = 'red'
nextCoordinate.zIndex = 1
} else {
nextCoordinate.background = null
}

const nextCoordinates = update(index, nextCoordinate)(coordinates)
if (is(Function, onResize)) {
onResize(nextCoordinate, index, nextCoordinates)
Expand All @@ -75,9 +116,19 @@ class Crop extends Component {
coordinates,
onDrag,
onChange,
permitAreaOverlap,
} = this.props
const { dx, dy } = e

const nextCoordinate = { ...coordinate, x: x + dx, y: y + dy }

if (!permitAreaOverlap && areaNotAvailable(coordinates, coordinate)) {
nextCoordinate.background = 'red'
nextCoordinate.zIndex = 1
} else {
nextCoordinate.background = null
}

const nextCoordinates = update(index, nextCoordinate)(coordinates)
if (is(Function, onDrag)) {
onDrag(nextCoordinate, index, nextCoordinates)
Expand Down Expand Up @@ -138,7 +189,9 @@ Crop.propTypes = {
onDrag: PropTypes.func, // eslint-disable-line
onDelete: PropTypes.func, // eslint-disable-line
onChange: PropTypes.func, // eslint-disable-line
coordinates: PropTypes.array // eslint-disable-line
coordinates: PropTypes.array, // eslint-disable-line
permitAreaOverlap: PropTypes.bool, // eslint-disable-line
previus: PropTypes.any // eslint-disable-line
}

export default Crop
58 changes: 50 additions & 8 deletions src/components/MultiCrops.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { both, clone, is, complement, equals, map, addIndex } from 'ramda'
import PropTypes from 'prop-types'
import shortid from 'shortid'
import Crop, { coordinateType } from './Crop'

import { areaNotAvailable } from '../utils'

const isValidPoint = (point = {}) => {
const strictNumber = number => both(
Expand Down Expand Up @@ -54,7 +54,13 @@ class MultiCrops extends Component {


handleMouseMove = (e) => {
const { onDraw, onChange, coordinates } = this.props
const {
onDraw,
onChange,
coordinates,
permitAreaOverlap,
} = this.props

const { pointA } = this
if (isValidPoint(pointA)) {
const pointB = this.getCursorPosition(e)
Expand All @@ -67,6 +73,16 @@ class MultiCrops extends Component {
height: Math.abs(pointA.y - pointB.y),
id: this.id,
}

const elementIntoArea = areaNotAvailable(coordinates, coordinate)

if (!permitAreaOverlap && elementIntoArea) {
coordinate.background = 'red'
coordinate.zIndex = 1
} else {
coordinate.background = null
}

const nextCoordinates = clone(coordinates)
nextCoordinates[this.drawingIndex] = coordinate
if (is(Function, onDraw)) {
Expand All @@ -79,6 +95,30 @@ class MultiCrops extends Component {
}

handlMouseUp = () => {
const { coordinates, onDraw, onChange } = this.props

let deleteIndex
let coordinate

coordinates.forEach((element, index) => {
if (element.id === this.id) {
deleteIndex = index
coordinate = element
}
})

if (coordinate && coordinate.background === 'red') {
coordinates.splice(deleteIndex, 1)

const nextCoordinates = clone(coordinates)
if (is(Function, onDraw)) {
onDraw(coordinate, this.drawingIndex, nextCoordinates)
}
if (is(Function, onChange)) {
onChange(coordinate, this.drawingIndex, nextCoordinates)
}
}

this.pointA = {}
}

Expand Down Expand Up @@ -115,22 +155,24 @@ class MultiCrops extends Component {
}

const {
string, arrayOf, number, func,
string, arrayOf, number, func, bool,
} = PropTypes

MultiCrops.propTypes = {
coordinates: arrayOf(coordinateType),
src: string,
width: number, // eslint-disable-line
height: number, // eslint-disable-line
onDraw: func, // eslint-disable-line
onChange: func, // eslint-disable-line
onLoad: func, // eslint-disable-line
width: number,
height: number,
onDraw: func,
onChange: func,
onLoad: func,
permitAreaOverlap: bool,
}

MultiCrops.defaultProps = {
coordinates: [],
src: '',
permitAreaOverlap: true,
}

export default MultiCrops
Expand Down
30 changes: 30 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,33 @@ import { map, assoc, omit } from 'ramda'
export const addid = map(assoc('id', shortid.generate()))

export const removeid = map(omit(['id']))

export const isOverlapping = (self, other) => {
const left = self.x
const right = self.x + self.width
const top = self.y
const bottom = self.y + self.height
const otherleft = other.x
const otherright = other.x + other.width
const othertop = other.y
const otherbottom = other.y + other.height
return left <= otherright && right >= otherleft && top <= otherbottom && bottom >= othertop
}

export const areaNotAvailable = (coordinates, coordinate) => {
let canContinue

// eslint-disable-next-line no-plusplus
for (let i = 0; i < coordinates.length; i++) {
const element = coordinates[i]
if (element.id === coordinate.id) {
// eslint-disable-next-line no-continue
continue
}
if (isOverlapping(element, coordinate)) {
canContinue = element
break
}
}
return canContinue
}