Skip to content
Merged
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
8 changes: 8 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"env": {
"dev": {},
"test": {
"presets": ["env", "react"]
}
}
}
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ install:

build:
yarn run build

test:
yarn test
11 changes: 3 additions & 8 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@ var initGulpTasks = require('react-component-gulp-tasks');
*/

var taskConfig = {

component: {
name: 'Crop',
dependencies: [
'react',
'react-dom'
],
lib: 'lib'
}

dependencies: ['react', 'react-dom'],
lib: 'lib',
},
};

initGulpTasks(gulp, taskConfig);
250 changes: 149 additions & 101 deletions lib/Crop.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint class-methods-use-this: ["error", { "exceptMethods": ["_distance", "_eventCoordinates"] }] */

'use strict';

Object.defineProperty(exports, '__esModule', {
Expand All @@ -20,33 +22,122 @@ var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var Crop = (function (_Component) {
_inherits(Crop, _Component);

function Crop() {
function Crop(props) {
var _this = this;

_classCallCheck(this, Crop);

_get(Object.getPrototypeOf(Crop.prototype), 'constructor', this).call(this);
_get(Object.getPrototypeOf(Crop.prototype), 'constructor', this).call(this, props);
this.state = {
drag: null,
image: null,
pinch: null
image: null
};
this.listeners = {
start: null,
move: null,
end: null
};
this.setCanvasRef = function (el) {
_this.canvas = el;
};
this.setZoomRef = function (el) {
_this.zoom = el;
};
}

_createClass(Crop, [{
key: 'updateZoom',
value: function updateZoom() {
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;

var factor = this.refs.zoom.value;
this.prepareImage();

this.listeners = {
move: function move(e) {
return _this2.dragMove(e);
},
start: function start(e) {
return _this2.dragStart(e);
},
end: function end(e) {
return _this2.dragEnd(e);
},
select: function select(e) {
return _this2.dragNoSelect(e);
}
};

window.addEventListener('mousemove', this.listeners.move);
window.addEventListener('mouseup', this.listeners.end);
window.addEventListener('touchmove', this.listeners.move);
window.addEventListener('touchend', this.listeners.end);
this.canvas.addEventListener('mousedown', this.listeners.start);
this.canvas.addEventListener('touchstart', this.listeners.start);
document.onselectstart = this.listeners.select;
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(newProps) {
if (newProps.image !== this.props.image) {
this.prepareImage();
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
var image = this.state.image;
var _props = this.props;
var width = _props.width;
var height = _props.height;
var source = image.source;
var drawWidth = image.drawWidth;
var drawHeight = image.drawHeight;
var x = image.x;
var y = image.y;

var REGEXP_BLOB_URL = /^blob:.+\/[\w-]{36,}(?:#.+)?$/;
var isBlobOrFile = source.src instanceof Blob || source.src instanceof File || REGEXP_BLOB_URL.test(source.src);

var context = this.canvas.getContext('2d');
context.clearRect(0, 0, width, height);
if (isBlobOrFile) {
context.drawImage(source, x, y, drawWidth, drawHeight);
}
if (!isBlobOrFile) {
(function () {
// base64
var img = new Image();
img.onload = function () {
context.drawImage(img, x, y, drawWidth, drawHeight);
};
img.src = image.source;
})();
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
window.removeEventListener('touchmove', this.listeners.move);
window.removeEventListener('touchend', this.listeners.end);
window.removeEventListener('mousemove', this.listeners.move);
window.removeEventListener('mouseup', this.listeners.end);
this.canvas.removeEventListener('mousedown', this.listeners.start);
this.canvas.removeEventListener('touchstart', this.listeners.start);
}
}, {
key: 'updateZoom',
value: function updateZoom(level) {
var image = this.state.image;

var factor = level || this.zoom.value;

image.drawWidth = image.width * factor;
image.drawHeight = image.height * factor;
image.zoom = Math.abs(factor);
Expand All @@ -68,49 +159,39 @@ var Crop = (function (_Component) {
}, {
key: 'prepareImage',
value: function prepareImage() {
var _props = this.props;
var width = _props.width;
var height = _props.height;
var image = _props.image;
var _props2 = this.props;
var width = _props2.width;
var height = _props2.height;
var image = _props2.image;

var newWidth = undefined;
var newHeight = undefined;

if (image.width > image.height) {
newWidth = image.width * height / image.height;
newWidth = parseNumberToFixed(image.width * height / image.height);
newHeight = height;
} else {
newHeight = image.height * width / image.width;
newHeight = parseNumberToFixed(image.height * width / image.width);
newWidth = width;
}

this.setState({
image: {
source: this.props.image,
width: newWidth, height: newHeight,
x: 0, y: 0,
source: image.source || image,
width: newWidth,
height: newHeight,
x: 0,
y: 0,
zoom: 1,
drawWidth: newWidth, drawHeight: newHeight,
drawWidth: newWidth,
drawHeight: newHeight,
boundary: {
x: this.props.width - newWidth,
y: this.props.height - newHeight
x: width - newWidth,
y: height - newHeight
}
},
drag: null
});

this.refs.zoom.value = 1;
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
var canvas = this.refs.canvas;
var image = this.state.image;

var context = canvas.getContext('2d');

context.clearRect(0, 0, this.props.width, this.props.height);
context.drawImage(image.source, image.x, image.y, image.drawWidth, image.drawHeight);
}
}, {
key: '_distance',
Expand All @@ -134,12 +215,12 @@ var Crop = (function (_Component) {

var coordinates = this._eventCoordinates(e);

if (e.touches && e.touches.length == 2) {
if (e.touches && e.touches.length === 2) {
var _drag = {
pinch: {
max: this.props.width * Math.sqrt(2),
start: this._distance(e),
zoom: this.state.image.zoom
zoom: this.zoom.value
}
};
return this.setState({ drag: _drag });
Expand All @@ -163,7 +244,6 @@ var Crop = (function (_Component) {
}, {
key: 'dragMove',
value: function dragMove(e) {

if (!this.state.drag) return;

e.preventDefault();
Expand All @@ -186,10 +266,9 @@ var Crop = (function (_Component) {

newZoom = newZoom < 1 ? 1 : newZoom;
newZoom = newZoom > this.props.zoom ? this.props.zoom : newZoom;

this.refs.zoom.value = parseFloat(newZoom).toFixed(2);

this.updateZoom();
var parsedZoom = parseFloat(newZoom).toFixed(2);
this.zoom = parsedZoom;
this.updateZoom(parsedZoom);
}

var coordinates = this._eventCoordinates(e);
Expand Down Expand Up @@ -243,61 +322,10 @@ var Crop = (function (_Component) {

e.preventDefault();
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(newProps) {
if (newProps.image !== this.props.image) {
this.prepareImage();
}
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this = this;

this.prepareImage();

this.listeners = {
move: function move(e) {
return _this.dragMove(e);
},
start: function start(e) {
return _this.dragStart(e);
},
end: function end(e) {
return _this.dragEnd(e);
},
select: function select(e) {
return _this.dragNoSelect(e);
}
};

window.addEventListener('mousemove', this.listeners.move);
window.addEventListener('mouseup', this.listeners.end);
window.addEventListener('touchmove', this.listeners.move);
window.addEventListener('touchend', this.listeners.end);
this.refs.canvas.addEventListener('mousedown', this.listeners.start);
this.refs.canvas.addEventListener('touchstart', this.listeners.start);
document.onselectstart = this.listeners.select;
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
window.removeEventListener('touchmove', this.listeners.move);
window.removeEventListener('touchend', this.listeners.end);
window.removeEventListener('mousemove', this.listeners.move);
window.removeEventListener('mouseup', this.listeners.end);
this.refs.canvas.removeEventListener('mousedown', this.listeners.start);
this.refs.canvas.removeEventListener('touchstart', this.listeners.start);
}
}, {
key: 'getDataURL',
value: function getDataURL() {
return this.refs.canvas.toDataURL();
}
}, {
key: 'render',
value: function render() {
var _this3 = this;

var style = _extends({}, this.props.style || {}, { cursor: 'move' });

Expand All @@ -309,10 +337,13 @@ var Crop = (function (_Component) {
null,
_react2['default'].createElement('input', {
type: 'range',
ref: 'zoom',
onChange: this.updateZoom.bind(this),
onMouseMove: this.updateZoom.bind(this),
//onMouseUp={this.updateZoom.bind(this)}
ref: this.setZoomRef,
onChange: function () {
return _this3.updateZoom();
},
onMouseMove: function () {
return _this3.updateZoom();
},
style: { width: this.props.width, cursor: 'pointer' },
min: '1',
max: this.props.zoom,
Expand All @@ -328,7 +359,12 @@ var Crop = (function (_Component) {
_react2['default'].createElement(
'div',
null,
_react2['default'].createElement('canvas', { style: style, width: this.props.width, height: this.props.height, ref: 'canvas' })
_react2['default'].createElement('canvas', {
style: style,
width: this.props.width,
height: this.props.height,
ref: this.setCanvasRef
})
),
zoom
);
Expand All @@ -338,12 +374,24 @@ var Crop = (function (_Component) {
return Crop;
})(_react.Component);

function parseNumberToFixed(x) {
if (Number.isNaN(Number.parseFloat(x))) {
return 0;
}
return Number.parseFloat(x).toFixed(0);
}

Crop.defaultProps = {
zoom: undefined,
style: {}
};

Crop.propTypes = {
width: _react2['default'].PropTypes.number.isRequired,
height: _react2['default'].PropTypes.number.isRequired,
zoom: _react2['default'].PropTypes.number,
image: _react2['default'].PropTypes.object.isRequired,
style: _react2['default'].PropTypes.object
width: _propTypes2['default'].number.isRequired,
height: _propTypes2['default'].number.isRequired,
zoom: _propTypes2['default'].number,
image: _propTypes2['default'].object.isRequired,
style: _propTypes2['default'].object
};

exports['default'] = Crop;
Expand Down
Loading