1190 lines
41 KiB
JavaScript
1190 lines
41 KiB
JavaScript
|
/**
|
||
|
* Croppr.js
|
||
|
* https://github.com/jamesssooi/Croppr.js
|
||
|
*
|
||
|
* A JavaScript image cropper that's lightweight, awesome, and has
|
||
|
* zero dependencies.
|
||
|
*
|
||
|
* (C) 2017 James Ooi. Released under the MIT License.
|
||
|
*/
|
||
|
|
||
|
(function (global, factory) {
|
||
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||
|
typeof define === 'function' && define.amd ? define(factory) :
|
||
|
(global.Croppr = factory());
|
||
|
}(this, (function () { 'use strict';
|
||
|
|
||
|
(function () {
|
||
|
var lastTime = 0;
|
||
|
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
||
|
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||
|
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
|
||
|
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
|
||
|
}
|
||
|
if (!window.requestAnimationFrame) window.requestAnimationFrame = function (callback, element) {
|
||
|
var currTime = new Date().getTime();
|
||
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||
|
var id = window.setTimeout(function () {
|
||
|
callback(currTime + timeToCall);
|
||
|
}, timeToCall);
|
||
|
lastTime = currTime + timeToCall;
|
||
|
return id;
|
||
|
};
|
||
|
if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function (id) {
|
||
|
clearTimeout(id);
|
||
|
};
|
||
|
})();
|
||
|
(function () {
|
||
|
if (typeof window.CustomEvent === "function") return false;
|
||
|
function CustomEvent(event, params) {
|
||
|
params = params || { bubbles: false, cancelable: false, detail: undefined };
|
||
|
var evt = document.createEvent('CustomEvent');
|
||
|
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
|
||
|
return evt;
|
||
|
}
|
||
|
CustomEvent.prototype = window.Event.prototype;
|
||
|
window.CustomEvent = CustomEvent;
|
||
|
})();
|
||
|
(function (window) {
|
||
|
try {
|
||
|
new CustomEvent('test');
|
||
|
return false;
|
||
|
} catch (e) {}
|
||
|
function MouseEvent(eventType, params) {
|
||
|
params = params || { bubbles: false, cancelable: false };
|
||
|
var mouseEvent = document.createEvent('MouseEvent');
|
||
|
mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||
|
return mouseEvent;
|
||
|
}
|
||
|
MouseEvent.prototype = Event.prototype;
|
||
|
window.MouseEvent = MouseEvent;
|
||
|
})(window);
|
||
|
|
||
|
var classCallCheck = function (instance, Constructor) {
|
||
|
if (!(instance instanceof Constructor)) {
|
||
|
throw new TypeError("Cannot call a class as a function");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var createClass = function () {
|
||
|
function defineProperties(target, props) {
|
||
|
for (var i = 0; i < props.length; i++) {
|
||
|
var descriptor = props[i];
|
||
|
descriptor.enumerable = descriptor.enumerable || false;
|
||
|
descriptor.configurable = true;
|
||
|
if ("value" in descriptor) descriptor.writable = true;
|
||
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return function (Constructor, protoProps, staticProps) {
|
||
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||
|
return Constructor;
|
||
|
};
|
||
|
}();
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
var get = function get(object, property, receiver) {
|
||
|
if (object === null) object = Function.prototype;
|
||
|
var desc = Object.getOwnPropertyDescriptor(object, property);
|
||
|
|
||
|
if (desc === undefined) {
|
||
|
var parent = Object.getPrototypeOf(object);
|
||
|
|
||
|
if (parent === null) {
|
||
|
return undefined;
|
||
|
} else {
|
||
|
return get(parent, property, receiver);
|
||
|
}
|
||
|
} else if ("value" in desc) {
|
||
|
return desc.value;
|
||
|
} else {
|
||
|
var getter = desc.get;
|
||
|
|
||
|
if (getter === undefined) {
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
return getter.call(receiver);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var inherits = function (subClass, superClass) {
|
||
|
if (typeof superClass !== "function" && superClass !== null) {
|
||
|
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
||
|
}
|
||
|
|
||
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
||
|
constructor: {
|
||
|
value: subClass,
|
||
|
enumerable: false,
|
||
|
writable: true,
|
||
|
configurable: true
|
||
|
}
|
||
|
});
|
||
|
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
var possibleConstructorReturn = function (self, call) {
|
||
|
if (!self) {
|
||
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
||
|
}
|
||
|
|
||
|
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
var slicedToArray = function () {
|
||
|
function sliceIterator(arr, i) {
|
||
|
var _arr = [];
|
||
|
var _n = true;
|
||
|
var _d = false;
|
||
|
var _e = undefined;
|
||
|
|
||
|
try {
|
||
|
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
||
|
_arr.push(_s.value);
|
||
|
|
||
|
if (i && _arr.length === i) break;
|
||
|
}
|
||
|
} catch (err) {
|
||
|
_d = true;
|
||
|
_e = err;
|
||
|
} finally {
|
||
|
try {
|
||
|
if (!_n && _i["return"]) _i["return"]();
|
||
|
} finally {
|
||
|
if (_d) throw _e;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return _arr;
|
||
|
}
|
||
|
|
||
|
return function (arr, i) {
|
||
|
if (Array.isArray(arr)) {
|
||
|
return arr;
|
||
|
} else if (Symbol.iterator in Object(arr)) {
|
||
|
return sliceIterator(arr, i);
|
||
|
} else {
|
||
|
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
||
|
}
|
||
|
};
|
||
|
}();
|
||
|
|
||
|
var Handle =
|
||
|
/**
|
||
|
* Creates a new Handle instance.
|
||
|
* @constructor
|
||
|
* @param {Array} position The x and y ratio position of the handle
|
||
|
* within the crop region. Accepts a value between 0 to 1 in the order
|
||
|
* of [X, Y].
|
||
|
* @param {Array} constraints Define the side of the crop region that
|
||
|
* is to be affected by this handle. Accepts a value of 0 or 1 in the
|
||
|
* order of [TOP, RIGHT, BOTTOM, LEFT].
|
||
|
* @param {String} cursor The CSS cursor of this handle.
|
||
|
* @param {Element} eventBus The element to dispatch events to.
|
||
|
*/
|
||
|
function Handle(position, constraints, cursor, eventBus) {
|
||
|
classCallCheck(this, Handle);
|
||
|
var self = this;
|
||
|
this.position = position;
|
||
|
this.constraints = constraints;
|
||
|
this.cursor = cursor;
|
||
|
this.eventBus = eventBus;
|
||
|
this.el = document.createElement('div');
|
||
|
this.el.className = 'croppr-handle';
|
||
|
this.el.style.cursor = cursor;
|
||
|
this.el.addEventListener('mousedown', onMouseDown);
|
||
|
function onMouseDown(e) {
|
||
|
e.stopPropagation();
|
||
|
document.addEventListener('mouseup', onMouseUp);
|
||
|
document.addEventListener('mousemove', onMouseMove);
|
||
|
self.eventBus.dispatchEvent(new CustomEvent('handlestart', {
|
||
|
detail: { handle: self }
|
||
|
}));
|
||
|
}
|
||
|
function onMouseUp(e) {
|
||
|
e.stopPropagation();
|
||
|
document.removeEventListener('mouseup', onMouseUp);
|
||
|
document.removeEventListener('mousemove', onMouseMove);
|
||
|
self.eventBus.dispatchEvent(new CustomEvent('handleend', {
|
||
|
detail: { handle: self }
|
||
|
}));
|
||
|
}
|
||
|
function onMouseMove(e) {
|
||
|
e.stopPropagation();
|
||
|
self.eventBus.dispatchEvent(new CustomEvent('handlemove', {
|
||
|
detail: { mouseX: e.clientX, mouseY: e.clientY }
|
||
|
}));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var Box = function () {
|
||
|
/**
|
||
|
* Creates a new Box instance.
|
||
|
* @constructor
|
||
|
* @param {Number} x1
|
||
|
* @param {Number} y1
|
||
|
* @param {Number} x2
|
||
|
* @param {Number} y2
|
||
|
*/
|
||
|
function Box(x1, y1, x2, y2) {
|
||
|
classCallCheck(this, Box);
|
||
|
this.x1 = x1;
|
||
|
this.y1 = y1;
|
||
|
this.x2 = x2;
|
||
|
this.y2 = y2;
|
||
|
}
|
||
|
/**
|
||
|
* Sets the new dimensions of the box.
|
||
|
* @param {Number} x1
|
||
|
* @param {Number} y1
|
||
|
* @param {Number} x2
|
||
|
* @param {Number} y2
|
||
|
*/
|
||
|
createClass(Box, [{
|
||
|
key: 'set',
|
||
|
value: function set$$1() {
|
||
|
var x1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||
|
var y1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||
|
var x2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||
|
var y2 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
||
|
this.x1 = x1 == null ? this.x1 : x1;
|
||
|
this.y1 = y1 == null ? this.y1 : y1;
|
||
|
this.x2 = x2 == null ? this.x2 : x2;
|
||
|
this.y2 = y2 == null ? this.y2 : y2;
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Calculates the width of the box.
|
||
|
* @returns {Number}
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'width',
|
||
|
value: function width() {
|
||
|
return Math.abs(this.x2 - this.x1);
|
||
|
}
|
||
|
/**
|
||
|
* Calculates the height of the box.
|
||
|
* @returns {Number}
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'height',
|
||
|
value: function height() {
|
||
|
return Math.abs(this.y2 - this.y1);
|
||
|
}
|
||
|
/**
|
||
|
* Resizes the box to a new size.
|
||
|
* @param {Number} newWidth
|
||
|
* @param {Number} newHeight
|
||
|
* @param {Array} [origin] The origin point to resize from.
|
||
|
* Defaults to [0, 0] (top left).
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'resize',
|
||
|
value: function resize(newWidth, newHeight) {
|
||
|
var origin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
|
||
|
var fromX = this.x1 + this.width() * origin[0];
|
||
|
var fromY = this.y1 + this.height() * origin[1];
|
||
|
this.x1 = fromX - newWidth * origin[0];
|
||
|
this.y1 = fromY - newHeight * origin[1];
|
||
|
this.x2 = this.x1 + newWidth;
|
||
|
this.y2 = this.y1 + newHeight;
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Scale the box by a factor.
|
||
|
* @param {Number} factor
|
||
|
* @param {Array} [origin] The origin point to resize from.
|
||
|
* Defaults to [0, 0] (top left).
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'scale',
|
||
|
value: function scale(factor) {
|
||
|
var origin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0, 0];
|
||
|
var newWidth = this.width() * factor;
|
||
|
var newHeight = this.height() * factor;
|
||
|
this.resize(newWidth, newHeight, origin);
|
||
|
return this;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'move',
|
||
|
value: function move() {
|
||
|
var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||
|
var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||
|
var width = this.width();
|
||
|
var height = this.height();
|
||
|
x = x === null ? this.x1 : x;
|
||
|
y = y === null ? this.y1 : y;
|
||
|
this.x1 = x;
|
||
|
this.y1 = y;
|
||
|
this.x2 = x + width;
|
||
|
this.y2 = y + height;
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Get relative x and y coordinates of a given point within the box.
|
||
|
* @param {Array} point The x and y ratio position within the box.
|
||
|
* @returns {Array} The x and y coordinates [x, y].
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'getRelativePoint',
|
||
|
value: function getRelativePoint() {
|
||
|
var point = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0];
|
||
|
var x = this.width() * point[0];
|
||
|
var y = this.height() * point[1];
|
||
|
return [x, y];
|
||
|
}
|
||
|
/**
|
||
|
* Get absolute x and y coordinates of a given point within the box.
|
||
|
* @param {Array} point The x and y ratio position within the box.
|
||
|
* @returns {Array} The x and y coordinates [x, y].
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'getAbsolutePoint',
|
||
|
value: function getAbsolutePoint() {
|
||
|
var point = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0];
|
||
|
var x = this.x1 + this.width() * point[0];
|
||
|
var y = this.y1 + this.height() * point[1];
|
||
|
return [x, y];
|
||
|
}
|
||
|
/**
|
||
|
* Constrain the box to a fixed ratio.
|
||
|
* @param {Number} ratio
|
||
|
* @param {Array} [origin] The origin point to resize from.
|
||
|
* Defaults to [0, 0] (top left).
|
||
|
* @param {String} [grow] The axis to grow to maintain the ratio.
|
||
|
* Defaults to 'height'.
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'constrainToRatio',
|
||
|
value: function constrainToRatio(ratio) {
|
||
|
var origin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0, 0];
|
||
|
var grow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'height';
|
||
|
if (ratio === null) {
|
||
|
return;
|
||
|
}
|
||
|
var width = this.width();
|
||
|
var height = this.height();
|
||
|
switch (grow) {
|
||
|
case 'height':
|
||
|
this.resize(this.width(), this.width() * ratio, origin);
|
||
|
break;
|
||
|
case 'width':
|
||
|
this.resize(this.height() * 1 / ratio, this.height(), origin);
|
||
|
break;
|
||
|
default:
|
||
|
this.resize(this.width(), this.width() * ratio, origin);
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Constrain the box within a boundary.
|
||
|
* @param {Number} boundaryWidth
|
||
|
* @param {Number} boundaryHeight
|
||
|
* @param {Array} [origin] The origin point to resize from.
|
||
|
* Defaults to [0, 0] (top left).
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'constrainToBoundary',
|
||
|
value: function constrainToBoundary(boundaryWidth, boundaryHeight) {
|
||
|
var origin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
|
||
|
var _getAbsolutePoint = this.getAbsolutePoint(origin),
|
||
|
_getAbsolutePoint2 = slicedToArray(_getAbsolutePoint, 2),
|
||
|
originX = _getAbsolutePoint2[0],
|
||
|
originY = _getAbsolutePoint2[1];
|
||
|
var maxIfLeft = originX;
|
||
|
var maxIfTop = originY;
|
||
|
var maxIfRight = boundaryWidth - originX;
|
||
|
var maxIfBottom = boundaryHeight - originY;
|
||
|
var directionX = -2 * origin[0] + 1;
|
||
|
var directionY = -2 * origin[1] + 1;
|
||
|
var maxWidth = null,
|
||
|
maxHeight = null;
|
||
|
switch (directionX) {
|
||
|
case -1:
|
||
|
maxWidth = maxIfLeft;break;
|
||
|
case 0:
|
||
|
maxWidth = Math.min(maxIfLeft, maxIfRight) * 2;break;
|
||
|
case +1:
|
||
|
maxWidth = maxIfRight;break;
|
||
|
}
|
||
|
switch (directionY) {
|
||
|
case -1:
|
||
|
maxHeight = maxIfTop;break;
|
||
|
case 0:
|
||
|
maxHeight = Math.min(maxIfTop, maxIfBottom) * 2;break;
|
||
|
case +1:
|
||
|
maxHeight = maxIfBottom;break;
|
||
|
}
|
||
|
if (this.width() > maxWidth) {
|
||
|
var factor = maxWidth / this.width();
|
||
|
this.scale(factor, origin);
|
||
|
}
|
||
|
if (this.height() > maxHeight) {
|
||
|
var _factor = maxHeight / this.height();
|
||
|
this.scale(_factor, origin);
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Constrain the box to a maximum/minimum size.
|
||
|
* @param {Number} [maxWidth]
|
||
|
* @param {Number} [maxHeight]
|
||
|
* @param {Number} [minWidth]
|
||
|
* @param {Number} [minHeight]
|
||
|
* @param {Array} [origin] The origin point to resize from.
|
||
|
* Defaults to [0, 0] (top left).
|
||
|
* @param {Number} [ratio] Ratio to maintain.
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'constrainToSize',
|
||
|
value: function constrainToSize() {
|
||
|
var maxWidth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||
|
var maxHeight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||
|
var minWidth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||
|
var minHeight = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
||
|
var origin = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [0, 0];
|
||
|
var ratio = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
|
||
|
if (ratio) {
|
||
|
if (ratio > 1) {
|
||
|
maxWidth = maxHeight * 1 / ratio;
|
||
|
minHeight = minHeight * ratio;
|
||
|
} else if (ratio < 1) {
|
||
|
maxHeight = maxWidth * ratio;
|
||
|
minWidth = minHeight * 1 / ratio;
|
||
|
}
|
||
|
}
|
||
|
if (maxWidth && this.width() > maxWidth) {
|
||
|
var newWidth = maxWidth,
|
||
|
newHeight = ratio === null ? this.height() : maxHeight;
|
||
|
this.resize(newWidth, newHeight, origin);
|
||
|
}
|
||
|
if (maxHeight && this.height() > maxHeight) {
|
||
|
var _newWidth = ratio === null ? this.width() : maxWidth,
|
||
|
_newHeight = maxHeight;
|
||
|
this.resize(_newWidth, _newHeight, origin);
|
||
|
}
|
||
|
if (minWidth && this.width() < minWidth) {
|
||
|
var _newWidth2 = minWidth,
|
||
|
_newHeight2 = ratio === null ? this.height() : minHeight;
|
||
|
this.resize(_newWidth2, _newHeight2, origin);
|
||
|
}
|
||
|
if (minHeight && this.height() < minHeight) {
|
||
|
var _newWidth3 = ratio === null ? this.width() : minWidth,
|
||
|
_newHeight3 = minHeight;
|
||
|
this.resize(_newWidth3, _newHeight3, origin);
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
}]);
|
||
|
return Box;
|
||
|
}();
|
||
|
|
||
|
/**
|
||
|
* Binds an element's touch events to be simulated as mouse events.
|
||
|
* @param {Element} element
|
||
|
*/
|
||
|
function enableTouch(element) {
|
||
|
element.addEventListener('touchstart', simulateMouseEvent);
|
||
|
element.addEventListener('touchend', simulateMouseEvent);
|
||
|
element.addEventListener('touchmove', simulateMouseEvent);
|
||
|
}
|
||
|
/**
|
||
|
* Translates a touch event to a mouse event.
|
||
|
* @param {Event} e
|
||
|
*/
|
||
|
function simulateMouseEvent(e) {
|
||
|
e.preventDefault();
|
||
|
var touch = e.changedTouches[0];
|
||
|
var eventMap = {
|
||
|
'touchstart': 'mousedown',
|
||
|
'touchmove': 'mousemove',
|
||
|
'touchend': 'mouseup'
|
||
|
};
|
||
|
touch.target.dispatchEvent(new MouseEvent(eventMap[e.type], {
|
||
|
bubbles: true,
|
||
|
cancelable: true,
|
||
|
view: window,
|
||
|
clientX: touch.clientX,
|
||
|
clientY: touch.clientY,
|
||
|
screenX: touch.screenX,
|
||
|
screenY: touch.screenY
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Define a list of handles to create.
|
||
|
*
|
||
|
* @property {Array} position - The x and y ratio position of the handle within
|
||
|
* the crop region. Accepts a value between 0 to 1 in the order of [X, Y].
|
||
|
* @property {Array} constraints - Define the side of the crop region that is to
|
||
|
* be affected by this handle. Accepts a value of 0 or 1 in the order of
|
||
|
* [TOP, RIGHT, BOTTOM, LEFT].
|
||
|
* @property {String} cursor - The CSS cursor of this handle.
|
||
|
*/
|
||
|
var HANDLES = [{ position: [0.0, 0.0], constraints: [1, 0, 0, 1], cursor: 'nw-resize' }, { position: [0.5, 0.0], constraints: [1, 0, 0, 0], cursor: 'n-resize' }, { position: [1.0, 0.0], constraints: [1, 1, 0, 0], cursor: 'ne-resize' }, { position: [1.0, 0.5], constraints: [0, 1, 0, 0], cursor: 'e-resize' }, { position: [1.0, 1.0], constraints: [0, 1, 1, 0], cursor: 'se-resize' }, { position: [0.5, 1.0], constraints: [0, 0, 1, 0], cursor: 's-resize' }, { position: [0.0, 1.0], constraints: [0, 0, 1, 1], cursor: 'sw-resize' }, { position: [0.0, 0.5], constraints: [0, 0, 0, 1], cursor: 'w-resize' }];
|
||
|
var CropprCore = function () {
|
||
|
function CropprCore(element, options) {
|
||
|
var _this = this;
|
||
|
var deferred = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
||
|
classCallCheck(this, CropprCore);
|
||
|
this.options = CropprCore.parseOptions(options || {});
|
||
|
if (!element.nodeName) {
|
||
|
element = document.querySelector(element);
|
||
|
if (element == null) {
|
||
|
throw 'Unable to find element.';
|
||
|
}
|
||
|
}
|
||
|
if (!element.getAttribute('src')) {
|
||
|
throw 'Image src not provided.';
|
||
|
}
|
||
|
this._initialized = false;
|
||
|
this._restore = {
|
||
|
parent: element.parentNode,
|
||
|
element: element
|
||
|
};
|
||
|
if (!deferred) {
|
||
|
if (element.width === 0 || element.height === 0) {
|
||
|
element.onload = function () {
|
||
|
_this.initialize(element);
|
||
|
};
|
||
|
} else {
|
||
|
this.initialize(element);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
createClass(CropprCore, [{
|
||
|
key: 'initialize',
|
||
|
value: function initialize(element) {
|
||
|
this.createDOM(element);
|
||
|
this.options.convertToPixels(this.cropperEl);
|
||
|
this.attachHandlerEvents();
|
||
|
this.attachRegionEvents();
|
||
|
this.attachOverlayEvents();
|
||
|
this.box = this.initializeBox(this.options);
|
||
|
this.redraw();
|
||
|
this._initialized = true;
|
||
|
if (this.options.onInitialize !== null) {
|
||
|
this.options.onInitialize(this);
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'createDOM',
|
||
|
value: function createDOM(targetEl) {
|
||
|
this.containerEl = document.createElement('div');
|
||
|
this.containerEl.className = 'croppr-container';
|
||
|
this.eventBus = this.containerEl;
|
||
|
enableTouch(this.containerEl);
|
||
|
this.cropperEl = document.createElement('div');
|
||
|
this.cropperEl.className = 'croppr';
|
||
|
this.imageEl = document.createElement('img');
|
||
|
this.imageEl.setAttribute('src', targetEl.getAttribute('src'));
|
||
|
this.imageEl.setAttribute('alt', targetEl.getAttribute('alt'));
|
||
|
this.imageEl.className = 'croppr-image';
|
||
|
this.imageClippedEl = this.imageEl.cloneNode();
|
||
|
this.imageClippedEl.className = 'croppr-imageClipped';
|
||
|
this.regionEl = document.createElement('div');
|
||
|
this.regionEl.className = 'croppr-region';
|
||
|
this.overlayEl = document.createElement('div');
|
||
|
this.overlayEl.className = 'croppr-overlay';
|
||
|
var handleContainerEl = document.createElement('div');
|
||
|
handleContainerEl.className = 'croppr-handleContainer';
|
||
|
this.handles = [];
|
||
|
for (var i = 0; i < HANDLES.length; i++) {
|
||
|
var handle = new Handle(HANDLES[i].position, HANDLES[i].constraints, HANDLES[i].cursor, this.eventBus);
|
||
|
this.handles.push(handle);
|
||
|
handleContainerEl.appendChild(handle.el);
|
||
|
}
|
||
|
this.cropperEl.appendChild(this.imageEl);
|
||
|
this.cropperEl.appendChild(this.imageClippedEl);
|
||
|
this.cropperEl.appendChild(this.regionEl);
|
||
|
this.cropperEl.appendChild(this.overlayEl);
|
||
|
this.cropperEl.appendChild(handleContainerEl);
|
||
|
this.containerEl.appendChild(this.cropperEl);
|
||
|
targetEl.parentElement.replaceChild(this.containerEl, targetEl);
|
||
|
}
|
||
|
/**
|
||
|
* Changes the image src.
|
||
|
* @param {String} src
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'setImage',
|
||
|
value: function setImage(src) {
|
||
|
var _this2 = this;
|
||
|
this.imageEl.onload = function () {
|
||
|
_this2.box = _this2.initializeBox(_this2.options);
|
||
|
_this2.redraw();
|
||
|
};
|
||
|
this.imageEl.src = src;
|
||
|
this.imageClippedEl.src = src;
|
||
|
return this;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'destroy',
|
||
|
value: function destroy() {
|
||
|
this._restore.parent.replaceChild(this._restore.element, this.containerEl);
|
||
|
}
|
||
|
/**
|
||
|
* Create a new box region with a set of options.
|
||
|
* @param {Object} opts The options.
|
||
|
* @returns {Box}
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'initializeBox',
|
||
|
value: function initializeBox(opts) {
|
||
|
var width = opts.startSize.width;
|
||
|
var height = opts.startSize.height;
|
||
|
var box = new Box(0, 0, width, height);
|
||
|
box.constrainToRatio(opts.aspectRatio, [0.5, 0.5]);
|
||
|
var min = opts.minSize;
|
||
|
var max = opts.maxSize;
|
||
|
box.constrainToSize(max.width, max.height, min.width, min.height, [0.5, 0.5], opts.aspectRatio);
|
||
|
var parentWidth = this.cropperEl.offsetWidth;
|
||
|
var parentHeight = this.cropperEl.offsetHeight;
|
||
|
box.constrainToBoundary(parentWidth, parentHeight, [0.5, 0.5]);
|
||
|
var x = this.cropperEl.offsetWidth / 2 - box.width() / 2;
|
||
|
var y = this.cropperEl.offsetHeight / 2 - box.height() / 2;
|
||
|
box.move(x, y);
|
||
|
return box;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'redraw',
|
||
|
value: function redraw() {
|
||
|
var _this3 = this;
|
||
|
var width = Math.round(this.box.width()),
|
||
|
height = Math.round(this.box.height()),
|
||
|
x1 = Math.round(this.box.x1),
|
||
|
y1 = Math.round(this.box.y1),
|
||
|
x2 = Math.round(this.box.x2),
|
||
|
y2 = Math.round(this.box.y2);
|
||
|
window.requestAnimationFrame(function () {
|
||
|
_this3.regionEl.style.transform = 'translate(' + x1 + 'px, ' + y1 + 'px)';
|
||
|
_this3.regionEl.style.width = width + 'px';
|
||
|
_this3.regionEl.style.height = height + 'px';
|
||
|
_this3.imageClippedEl.style.clip = 'rect(' + y1 + 'px, ' + x2 + 'px, ' + y2 + 'px, ' + x1 + 'px)';
|
||
|
var center = _this3.box.getAbsolutePoint([.5, .5]);
|
||
|
var xSign = center[0] - _this3.cropperEl.offsetWidth / 2 >> 31;
|
||
|
var ySign = center[1] - _this3.cropperEl.offsetHeight / 2 >> 31;
|
||
|
var quadrant = (xSign ^ ySign) + ySign + ySign + 4;
|
||
|
var foregroundHandleIndex = -2 * quadrant + 8;
|
||
|
for (var i = 0; i < _this3.handles.length; i++) {
|
||
|
var handle = _this3.handles[i];
|
||
|
var handleWidth = handle.el.offsetWidth;
|
||
|
var handleHeight = handle.el.offsetHeight;
|
||
|
var left = x1 + width * handle.position[0] - handleWidth / 2;
|
||
|
var top = y1 + height * handle.position[1] - handleHeight / 2;
|
||
|
handle.el.style.transform = 'translate(' + Math.round(left) + 'px, ' + Math.round(top) + 'px)';
|
||
|
handle.el.style.zIndex = foregroundHandleIndex == i ? 5 : 4;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'attachHandlerEvents',
|
||
|
value: function attachHandlerEvents() {
|
||
|
var eventBus = this.eventBus;
|
||
|
eventBus.addEventListener('handlestart', this.onHandleMoveStart.bind(this));
|
||
|
eventBus.addEventListener('handlemove', this.onHandleMoveMoving.bind(this));
|
||
|
eventBus.addEventListener('handleend', this.onHandleMoveEnd.bind(this));
|
||
|
}
|
||
|
}, {
|
||
|
key: 'attachRegionEvents',
|
||
|
value: function attachRegionEvents() {
|
||
|
var eventBus = this.eventBus;
|
||
|
var self = this;
|
||
|
this.regionEl.addEventListener('mousedown', onMouseDown);
|
||
|
eventBus.addEventListener('regionstart', this.onRegionMoveStart.bind(this));
|
||
|
eventBus.addEventListener('regionmove', this.onRegionMoveMoving.bind(this));
|
||
|
eventBus.addEventListener('regionend', this.onRegionMoveEnd.bind(this));
|
||
|
function onMouseDown(e) {
|
||
|
e.stopPropagation();
|
||
|
document.addEventListener('mouseup', onMouseUp);
|
||
|
document.addEventListener('mousemove', onMouseMove);
|
||
|
eventBus.dispatchEvent(new CustomEvent('regionstart', {
|
||
|
detail: { mouseX: e.clientX, mouseY: e.clientY }
|
||
|
}));
|
||
|
}
|
||
|
function onMouseMove(e) {
|
||
|
e.stopPropagation();
|
||
|
eventBus.dispatchEvent(new CustomEvent('regionmove', {
|
||
|
detail: { mouseX: e.clientX, mouseY: e.clientY }
|
||
|
}));
|
||
|
}
|
||
|
function onMouseUp(e) {
|
||
|
e.stopPropagation();
|
||
|
document.removeEventListener('mouseup', onMouseUp);
|
||
|
document.removeEventListener('mousemove', onMouseMove);
|
||
|
eventBus.dispatchEvent(new CustomEvent('regionend', {
|
||
|
detail: { mouseX: e.clientX, mouseY: e.clientY }
|
||
|
}));
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'attachOverlayEvents',
|
||
|
value: function attachOverlayEvents() {
|
||
|
var SOUTHEAST_HANDLE_IDX = 4;
|
||
|
var self = this;
|
||
|
var tmpBox = null;
|
||
|
this.overlayEl.addEventListener('mousedown', onMouseDown);
|
||
|
function onMouseDown(e) {
|
||
|
e.stopPropagation();
|
||
|
document.addEventListener('mouseup', onMouseUp);
|
||
|
document.addEventListener('mousemove', onMouseMove);
|
||
|
var container = self.cropperEl.getBoundingClientRect();
|
||
|
var mouseX = e.clientX - container.left;
|
||
|
var mouseY = e.clientY - container.top;
|
||
|
tmpBox = self.box;
|
||
|
self.box = new Box(mouseX, mouseY, mouseX + 1, mouseY + 1);
|
||
|
self.eventBus.dispatchEvent(new CustomEvent('handlestart', {
|
||
|
detail: { handle: self.handles[SOUTHEAST_HANDLE_IDX] }
|
||
|
}));
|
||
|
}
|
||
|
function onMouseMove(e) {
|
||
|
e.stopPropagation();
|
||
|
self.eventBus.dispatchEvent(new CustomEvent('handlemove', {
|
||
|
detail: { mouseX: e.clientX, mouseY: e.clientY }
|
||
|
}));
|
||
|
}
|
||
|
function onMouseUp(e) {
|
||
|
e.stopPropagation();
|
||
|
document.removeEventListener('mouseup', onMouseUp);
|
||
|
document.removeEventListener('mousemove', onMouseMove);
|
||
|
if (self.box.width() === 1 && self.box.height() === 1) {
|
||
|
self.box = tmpBox;
|
||
|
return;
|
||
|
}
|
||
|
self.eventBus.dispatchEvent(new CustomEvent('handleend', {
|
||
|
detail: { mouseX: e.clientX, mouseY: e.clientY }
|
||
|
}));
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onHandleMoveStart',
|
||
|
value: function onHandleMoveStart(e) {
|
||
|
var handle = e.detail.handle;
|
||
|
var originPoint = [1 - handle.position[0], 1 - handle.position[1]];
|
||
|
var _box$getAbsolutePoint = this.box.getAbsolutePoint(originPoint),
|
||
|
_box$getAbsolutePoint2 = slicedToArray(_box$getAbsolutePoint, 2),
|
||
|
originX = _box$getAbsolutePoint2[0],
|
||
|
originY = _box$getAbsolutePoint2[1];
|
||
|
this.activeHandle = { handle: handle, originPoint: originPoint, originX: originX, originY: originY };
|
||
|
if (this.options.onCropStart !== null) {
|
||
|
this.options.onCropStart(this.getValue());
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onHandleMoveMoving',
|
||
|
value: function onHandleMoveMoving(e) {
|
||
|
var _e$detail = e.detail,
|
||
|
mouseX = _e$detail.mouseX,
|
||
|
mouseY = _e$detail.mouseY;
|
||
|
var container = this.cropperEl.getBoundingClientRect();
|
||
|
mouseX = mouseX - container.left;
|
||
|
mouseY = mouseY - container.top;
|
||
|
if (mouseX < 0) {
|
||
|
mouseX = 0;
|
||
|
} else if (mouseX > container.width) {
|
||
|
mouseX = container.width;
|
||
|
}
|
||
|
if (mouseY < 0) {
|
||
|
mouseY = 0;
|
||
|
} else if (mouseY > container.height) {
|
||
|
mouseY = container.height;
|
||
|
}
|
||
|
var origin = this.activeHandle.originPoint.slice();
|
||
|
var originX = this.activeHandle.originX;
|
||
|
var originY = this.activeHandle.originY;
|
||
|
var handle = this.activeHandle.handle;
|
||
|
var TOP_MOVABLE = handle.constraints[0] === 1;
|
||
|
var RIGHT_MOVABLE = handle.constraints[1] === 1;
|
||
|
var BOTTOM_MOVABLE = handle.constraints[2] === 1;
|
||
|
var LEFT_MOVABLE = handle.constraints[3] === 1;
|
||
|
var MULTI_AXIS = (LEFT_MOVABLE || RIGHT_MOVABLE) && (TOP_MOVABLE || BOTTOM_MOVABLE);
|
||
|
var x1 = LEFT_MOVABLE || RIGHT_MOVABLE ? originX : this.box.x1;
|
||
|
var x2 = LEFT_MOVABLE || RIGHT_MOVABLE ? originX : this.box.x2;
|
||
|
var y1 = TOP_MOVABLE || BOTTOM_MOVABLE ? originY : this.box.y1;
|
||
|
var y2 = TOP_MOVABLE || BOTTOM_MOVABLE ? originY : this.box.y2;
|
||
|
x1 = LEFT_MOVABLE ? mouseX : x1;
|
||
|
x2 = RIGHT_MOVABLE ? mouseX : x2;
|
||
|
y1 = TOP_MOVABLE ? mouseY : y1;
|
||
|
y2 = BOTTOM_MOVABLE ? mouseY : y2;
|
||
|
var isFlippedX = false,
|
||
|
isFlippedY = false;
|
||
|
if (LEFT_MOVABLE || RIGHT_MOVABLE) {
|
||
|
isFlippedX = LEFT_MOVABLE ? mouseX > originX : mouseX < originX;
|
||
|
}
|
||
|
if (TOP_MOVABLE || BOTTOM_MOVABLE) {
|
||
|
isFlippedY = TOP_MOVABLE ? mouseY > originY : mouseY < originY;
|
||
|
}
|
||
|
if (isFlippedX) {
|
||
|
var tmp = x1;x1 = x2;x2 = tmp;
|
||
|
origin[0] = 1 - origin[0];
|
||
|
}
|
||
|
if (isFlippedY) {
|
||
|
var _tmp = y1;y1 = y2;y2 = _tmp;
|
||
|
origin[1] = 1 - origin[1];
|
||
|
}
|
||
|
var box = new Box(x1, y1, x2, y2);
|
||
|
if (this.options.aspectRatio) {
|
||
|
var ratio = this.options.aspectRatio;
|
||
|
var isVerticalMovement = false;
|
||
|
if (MULTI_AXIS) {
|
||
|
isVerticalMovement = mouseY > box.y1 + ratio * box.width() || mouseY < box.y2 - ratio * box.width();
|
||
|
} else if (TOP_MOVABLE || BOTTOM_MOVABLE) {
|
||
|
isVerticalMovement = true;
|
||
|
}
|
||
|
var ratioMode = isVerticalMovement ? 'width' : 'height';
|
||
|
box.constrainToRatio(ratio, origin, ratioMode);
|
||
|
}
|
||
|
var min = this.options.minSize;
|
||
|
var max = this.options.maxSize;
|
||
|
box.constrainToSize(max.width, max.height, min.width, min.height, origin, this.options.aspectRatio);
|
||
|
var parentWidth = this.cropperEl.offsetWidth;
|
||
|
var parentHeight = this.cropperEl.offsetHeight;
|
||
|
box.constrainToBoundary(parentWidth, parentHeight, origin);
|
||
|
this.box = box;
|
||
|
this.redraw();
|
||
|
if (this.options.onCropMove !== null) {
|
||
|
this.options.onCropMove(this.getValue());
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onHandleMoveEnd',
|
||
|
value: function onHandleMoveEnd(e) {
|
||
|
if (this.options.onCropEnd !== null) {
|
||
|
this.options.onCropEnd(this.getValue());
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onRegionMoveStart',
|
||
|
value: function onRegionMoveStart(e) {
|
||
|
var _e$detail2 = e.detail,
|
||
|
mouseX = _e$detail2.mouseX,
|
||
|
mouseY = _e$detail2.mouseY;
|
||
|
var container = this.cropperEl.getBoundingClientRect();
|
||
|
mouseX = mouseX - container.left;
|
||
|
mouseY = mouseY - container.top;
|
||
|
this.currentMove = {
|
||
|
offsetX: mouseX - this.box.x1,
|
||
|
offsetY: mouseY - this.box.y1
|
||
|
};
|
||
|
if (this.options.onCropStart !== null) {
|
||
|
this.options.onCropStart(this.getValue());
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onRegionMoveMoving',
|
||
|
value: function onRegionMoveMoving(e) {
|
||
|
var _e$detail3 = e.detail,
|
||
|
mouseX = _e$detail3.mouseX,
|
||
|
mouseY = _e$detail3.mouseY;
|
||
|
var _currentMove = this.currentMove,
|
||
|
offsetX = _currentMove.offsetX,
|
||
|
offsetY = _currentMove.offsetY;
|
||
|
var container = this.cropperEl.getBoundingClientRect();
|
||
|
mouseX = mouseX - container.left;
|
||
|
mouseY = mouseY - container.top;
|
||
|
this.box.move(mouseX - offsetX, mouseY - offsetY);
|
||
|
if (this.box.x1 < 0) {
|
||
|
this.box.move(0, null);
|
||
|
}
|
||
|
if (this.box.x2 > container.width) {
|
||
|
this.box.move(container.width - this.box.width(), null);
|
||
|
}
|
||
|
if (this.box.y1 < 0) {
|
||
|
this.box.move(null, 0);
|
||
|
}
|
||
|
if (this.box.y2 > container.height) {
|
||
|
this.box.move(null, container.height - this.box.height());
|
||
|
}
|
||
|
this.redraw();
|
||
|
if (this.options.onCropMove !== null) {
|
||
|
this.options.onCropMove(this.getValue());
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onRegionMoveEnd',
|
||
|
value: function onRegionMoveEnd(e) {
|
||
|
if (this.options.onCropEnd !== null) {
|
||
|
this.options.onCropEnd(this.getValue());
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'getValue',
|
||
|
value: function getValue() {
|
||
|
var mode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||
|
if (mode === null) {
|
||
|
mode = this.options.returnMode;
|
||
|
}
|
||
|
if (mode == 'real') {
|
||
|
var actualWidth = this.imageEl.naturalWidth;
|
||
|
var actualHeight = this.imageEl.naturalHeight;
|
||
|
var _imageEl$getBoundingC = this.imageEl.getBoundingClientRect(),
|
||
|
elementWidth = _imageEl$getBoundingC.width,
|
||
|
elementHeight = _imageEl$getBoundingC.height;
|
||
|
var factorX = actualWidth / elementWidth;
|
||
|
var factorY = actualHeight / elementHeight;
|
||
|
return {
|
||
|
x: Math.round(this.box.x1 * factorX),
|
||
|
y: Math.round(this.box.y1 * factorY),
|
||
|
width: Math.round(this.box.width() * factorX),
|
||
|
height: Math.round(this.box.height() * factorY)
|
||
|
};
|
||
|
} else if (mode == 'ratio') {
|
||
|
var _imageEl$getBoundingC2 = this.imageEl.getBoundingClientRect(),
|
||
|
_elementWidth = _imageEl$getBoundingC2.width,
|
||
|
_elementHeight = _imageEl$getBoundingC2.height;
|
||
|
return {
|
||
|
x: round(this.box.x1 / _elementWidth, 3),
|
||
|
y: round(this.box.y1 / _elementHeight, 3),
|
||
|
width: round(this.box.width() / _elementWidth, 3),
|
||
|
height: round(this.box.height() / _elementHeight, 3)
|
||
|
};
|
||
|
} else if (mode == 'raw') {
|
||
|
return {
|
||
|
x: Math.round(this.box.x1),
|
||
|
y: Math.round(this.box.y1),
|
||
|
width: Math.round(this.box.width()),
|
||
|
height: Math.round(this.box.height())
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
}], [{
|
||
|
key: 'parseOptions',
|
||
|
value: function parseOptions(opts) {
|
||
|
var defaults$$1 = {
|
||
|
aspectRatio: null,
|
||
|
maxSize: { width: null, height: null },
|
||
|
minSize: { width: null, height: null },
|
||
|
startSize: { width: 100, height: 100, unit: '%' },
|
||
|
returnMode: 'real',
|
||
|
onInitialize: null,
|
||
|
onCropStart: null,
|
||
|
onCropMove: null,
|
||
|
onCropEnd: null
|
||
|
};
|
||
|
var aspectRatio = null;
|
||
|
if (opts.aspectRatio !== undefined) {
|
||
|
if (typeof opts.aspectRatio === 'number') {
|
||
|
aspectRatio = opts.aspectRatio;
|
||
|
} else if (opts.aspectRatio instanceof Array) {
|
||
|
aspectRatio = opts.aspectRatio[1] / opts.aspectRatio[0];
|
||
|
}
|
||
|
}
|
||
|
var maxSize = null;
|
||
|
if (opts.maxSize !== undefined && opts.maxSize !== null) {
|
||
|
maxSize = {
|
||
|
width: opts.maxSize[0] || null,
|
||
|
height: opts.maxSize[1] || null,
|
||
|
unit: opts.maxSize[2] || 'px'
|
||
|
};
|
||
|
}
|
||
|
var minSize = null;
|
||
|
if (opts.minSize !== undefined && opts.minSize !== null) {
|
||
|
minSize = {
|
||
|
width: opts.minSize[0] || null,
|
||
|
height: opts.minSize[1] || null,
|
||
|
unit: opts.minSize[2] || 'px'
|
||
|
};
|
||
|
}
|
||
|
var startSize = null;
|
||
|
if (opts.startSize !== undefined && opts.startSize !== null) {
|
||
|
startSize = {
|
||
|
width: opts.startSize[0] || null,
|
||
|
height: opts.startSize[1] || null,
|
||
|
unit: opts.startSize[2] || '%'
|
||
|
};
|
||
|
}
|
||
|
var onInitialize = null;
|
||
|
if (typeof opts.onInitialize === 'function') {
|
||
|
onInitialize = opts.onInitialize;
|
||
|
}
|
||
|
var onCropStart = null;
|
||
|
if (typeof opts.onCropStart === 'function') {
|
||
|
onCropStart = opts.onCropStart;
|
||
|
}
|
||
|
var onCropEnd = null;
|
||
|
if (typeof opts.onCropEnd === 'function') {
|
||
|
onCropEnd = opts.onCropEnd;
|
||
|
}
|
||
|
var onCropMove = null;
|
||
|
if (typeof opts.onUpdate === 'function') {
|
||
|
console.warn('Croppr.js: `onUpdate` is deprecated and will be removed in the next major release. Please use `onCropMove` or `onCropEnd` instead.');
|
||
|
onCropMove = opts.onUpdate;
|
||
|
}
|
||
|
if (typeof opts.onCropMove === 'function') {
|
||
|
onCropMove = opts.onCropMove;
|
||
|
}
|
||
|
var returnMode = null;
|
||
|
if (opts.returnMode !== undefined) {
|
||
|
var s = opts.returnMode.toLowerCase();
|
||
|
if (['real', 'ratio', 'raw'].indexOf(s) === -1) {
|
||
|
throw "Invalid return mode.";
|
||
|
}
|
||
|
returnMode = s;
|
||
|
}
|
||
|
var convertToPixels = function convertToPixels(container) {
|
||
|
var width = container.offsetWidth;
|
||
|
var height = container.offsetHeight;
|
||
|
var sizeKeys = ['maxSize', 'minSize', 'startSize'];
|
||
|
for (var i = 0; i < sizeKeys.length; i++) {
|
||
|
var key = sizeKeys[i];
|
||
|
if (this[key] !== null) {
|
||
|
if (this[key].unit == '%') {
|
||
|
if (this[key].width !== null) {
|
||
|
this[key].width = this[key].width / 100 * width;
|
||
|
}
|
||
|
if (this[key].height !== null) {
|
||
|
this[key].height = this[key].height / 100 * height;
|
||
|
}
|
||
|
}
|
||
|
delete this[key].unit;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var defaultValue = function defaultValue(v, d) {
|
||
|
return v !== null ? v : d;
|
||
|
};
|
||
|
return {
|
||
|
aspectRatio: defaultValue(aspectRatio, defaults$$1.aspectRatio),
|
||
|
maxSize: defaultValue(maxSize, defaults$$1.maxSize),
|
||
|
minSize: defaultValue(minSize, defaults$$1.minSize),
|
||
|
startSize: defaultValue(startSize, defaults$$1.startSize),
|
||
|
returnMode: defaultValue(returnMode, defaults$$1.returnMode),
|
||
|
onInitialize: defaultValue(onInitialize, defaults$$1.onInitialize),
|
||
|
onCropStart: defaultValue(onCropStart, defaults$$1.onCropStart),
|
||
|
onCropMove: defaultValue(onCropMove, defaults$$1.onCropMove),
|
||
|
onCropEnd: defaultValue(onCropEnd, defaults$$1.onCropEnd),
|
||
|
convertToPixels: convertToPixels
|
||
|
};
|
||
|
}
|
||
|
}]);
|
||
|
return CropprCore;
|
||
|
}();
|
||
|
function round(value, decimals) {
|
||
|
return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
|
||
|
}
|
||
|
|
||
|
var Croppr$1 = function (_CropprCore) {
|
||
|
inherits(Croppr, _CropprCore);
|
||
|
/**
|
||
|
* @constructor
|
||
|
* Calls the CropprCore's constructor.
|
||
|
*/
|
||
|
function Croppr(element, options) {
|
||
|
var _deferred = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
||
|
classCallCheck(this, Croppr);
|
||
|
return possibleConstructorReturn(this, (Croppr.__proto__ || Object.getPrototypeOf(Croppr)).call(this, element, options, _deferred));
|
||
|
}
|
||
|
/**
|
||
|
* Gets the value of the crop region.
|
||
|
* @param {String} [mode] Which mode of calculation to use: 'real', 'ratio' or
|
||
|
* 'raw'.
|
||
|
*/
|
||
|
createClass(Croppr, [{
|
||
|
key: 'getValue',
|
||
|
value: function getValue(mode) {
|
||
|
return get(Croppr.prototype.__proto__ || Object.getPrototypeOf(Croppr.prototype), 'getValue', this).call(this, mode);
|
||
|
}
|
||
|
/**
|
||
|
* Changes the image src.
|
||
|
* @param {String} src
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'setImage',
|
||
|
value: function setImage(src) {
|
||
|
return get(Croppr.prototype.__proto__ || Object.getPrototypeOf(Croppr.prototype), 'setImage', this).call(this, src);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'destroy',
|
||
|
value: function destroy() {
|
||
|
return get(Croppr.prototype.__proto__ || Object.getPrototypeOf(Croppr.prototype), 'destroy', this).call(this);
|
||
|
}
|
||
|
/**
|
||
|
* Moves the crop region to a specified coordinate.
|
||
|
* @param {Number} x
|
||
|
* @param {Number} y
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'moveTo',
|
||
|
value: function moveTo(x, y) {
|
||
|
this.box.move(x, y);
|
||
|
this.redraw();
|
||
|
if (this.options.onCropEnd !== null) {
|
||
|
this.options.onCropEnd(this.getValue());
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Resizes the crop region to a specified width and height.
|
||
|
* @param {Number} width
|
||
|
* @param {Number} height
|
||
|
* @param {Array} origin The origin point to resize from.
|
||
|
* Defaults to [0.5, 0.5] (center).
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'resizeTo',
|
||
|
value: function resizeTo(width, height) {
|
||
|
var origin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [.5, .5];
|
||
|
this.box.resize(width, height, origin);
|
||
|
this.redraw();
|
||
|
if (this.options.onCropEnd !== null) {
|
||
|
this.options.onCropEnd(this.getValue());
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Scale the crop region by a factor.
|
||
|
* @param {Number} factor
|
||
|
* @param {Array} origin The origin point to resize from.
|
||
|
* Defaults to [0.5, 0.5] (center).
|
||
|
*/
|
||
|
}, {
|
||
|
key: 'scaleBy',
|
||
|
value: function scaleBy(factor) {
|
||
|
var origin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [.5, .5];
|
||
|
this.box.scale(factor, origin);
|
||
|
this.redraw();
|
||
|
if (this.options.onCropEnd !== null) {
|
||
|
this.options.onCropEnd(this.getValue());
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'reset',
|
||
|
value: function reset() {
|
||
|
this.box = this.initializeBox(this.options);
|
||
|
this.redraw();
|
||
|
if (this.options.onCropEnd !== null) {
|
||
|
this.options.onCropEnd(this.getValue());
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
}]);
|
||
|
return Croppr;
|
||
|
}(CropprCore);
|
||
|
|
||
|
return Croppr$1;
|
||
|
|
||
|
})));
|