angular-img-cropper
Version:
Client side image cropper directive for AngularJS (rectangular area, aspect ratio, multi-touch)
954 lines (919 loc) • 70.5 kB
JavaScript
angular.module('angular-img-cropper', []).directive("imageCropper", ['$document', '$window', 'imageCropperDataShare', function ($document, $window, imageCropperDataShare) {
return {
scope: {
image: "=",
croppedImage: "=",
cropWidth: "=",
cropHeight: "=",
keepAspect: "=",
touchRadius: "=",
cropAreaBounds: "=",
minWidth: "=",
minHeight: "="
},
restrict: "A",
link: function (scope, element, attrs) {
var crop;
var __extends = __extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() {
this.constructor = d;
}
__.prototype = b.prototype;
d.prototype = new __();
};
var Handle = (function () {
function Handle(x, y, radius) {
this.over = false;
this.drag = false;
this.position = new Point(x, y);
this.offset = new Point(0, 0);
this.radius = radius;
}
Handle.prototype.setDrag = function (value) {
this.drag = value;
this.setOver(value);
};
Handle.prototype.draw = function (ctx) {
};
Handle.prototype.setOver = function (over) {
this.over = over;
};
Handle.prototype.touchInBounds = function (x, y) {
return (x > this.position.x - this.radius && x < this.position.x + this.radius && y > this.position.y - this.radius && y < this.position.y + this.radius);
};
Handle.prototype.getPosition = function () {
return this.position;
};
Handle.prototype.setPosition = function (x, y) {
this.position.x = x;
this.position.y = y;
};
return Handle;
})();
var PointPool = (function () {
function PointPool(inst) {
this.borrowed = 0; //for debugging
PointPool.instance = this;
var prev = null;
for (var i = 0; i < inst; i++) {
if (i === 0) {
this.firstAvailable = new Point();
prev = this.firstAvailable;
}
else {
var p = new Point();
prev.setNext(p);
prev = p;
}
}
}
PointPool.prototype.borrow = function (x, y) {
if (this.firstAvailable == null) {
throw "Pool exhausted";
}
this.borrowed++;
var p = this.firstAvailable;
this.firstAvailable = p.getNext();
p.x = x;
p.y = y;
return p;
};
PointPool.prototype.returnPoint = function (p) {
this.borrowed--;
p.x = 0;
p.y = 0;
p.setNext(this.firstAvailable);
this.firstAvailable = p;
};
return PointPool;
})();
var CropService = (function () {
function CropService() {
}
CropService.init = function (canvas) {
this.canvas = canvas;
this.ctx = this.canvas.getContext("2d");
};
CropService.DEG2RAD = 0.0174532925;
return CropService;
})();
var DragMarker = (function (_super) {
__extends(DragMarker, _super);
function DragMarker(x, y, radius) {
_super.call(this, x, y, radius);
this.iconPoints = new Array();
this.scaledIconPoints = new Array();
this.getDragIconPoints(this.iconPoints, 1);
this.getDragIconPoints(this.scaledIconPoints, 1.2);
}
DragMarker.prototype.draw = function (ctx) {
if (this.over || this.drag) {
this.drawIcon(ctx, this.scaledIconPoints);
}
else {
this.drawIcon(ctx, this.iconPoints);
}
};
DragMarker.prototype.getDragIconPoints = function (arr, scale) {
var maxLength = 17 * scale;
var arrowWidth = 14 * scale;
var arrowLength = 8 * scale;
var connectorThroat = 4 * scale;
arr.push(PointPool.instance.borrow(-connectorThroat / 2, maxLength - arrowLength));
arr.push(PointPool.instance.borrow(-arrowWidth / 2, maxLength - arrowLength));
arr.push(PointPool.instance.borrow(0, maxLength));
arr.push(PointPool.instance.borrow(arrowWidth / 2, maxLength - arrowLength));
arr.push(PointPool.instance.borrow(connectorThroat / 2, maxLength - arrowLength));
arr.push(PointPool.instance.borrow(connectorThroat / 2, connectorThroat / 2));
arr.push(PointPool.instance.borrow(maxLength - arrowLength, connectorThroat / 2));
arr.push(PointPool.instance.borrow(maxLength - arrowLength, arrowWidth / 2));
arr.push(PointPool.instance.borrow(maxLength, 0));
arr.push(PointPool.instance.borrow(maxLength - arrowLength, -arrowWidth / 2));
arr.push(PointPool.instance.borrow(maxLength - arrowLength, -connectorThroat / 2));
arr.push(PointPool.instance.borrow(connectorThroat / 2, -connectorThroat / 2));
arr.push(PointPool.instance.borrow(connectorThroat / 2, -maxLength + arrowLength));
arr.push(PointPool.instance.borrow(arrowWidth / 2, -maxLength + arrowLength));
arr.push(PointPool.instance.borrow(0, -maxLength));
arr.push(PointPool.instance.borrow(-arrowWidth / 2, -maxLength + arrowLength));
arr.push(PointPool.instance.borrow(-connectorThroat / 2, -maxLength + arrowLength));
arr.push(PointPool.instance.borrow(-connectorThroat / 2, -connectorThroat / 2));
arr.push(PointPool.instance.borrow(-maxLength + arrowLength, -connectorThroat / 2));
arr.push(PointPool.instance.borrow(-maxLength + arrowLength, -arrowWidth / 2));
arr.push(PointPool.instance.borrow(-maxLength, 0));
arr.push(PointPool.instance.borrow(-maxLength + arrowLength, arrowWidth / 2));
arr.push(PointPool.instance.borrow(-maxLength + arrowLength, connectorThroat / 2));
arr.push(PointPool.instance.borrow(-connectorThroat / 2, connectorThroat / 2));
};
DragMarker.prototype.drawIcon = function (ctx, points) {
ctx.beginPath();
ctx.moveTo(points[0].x + this.position.x, points[0].y + this.position.y);
for (var k = 0; k < points.length; k++) {
var p = points[k];
ctx.lineTo(p.x + this.position.x, p.y + this.position.y);
}
ctx.closePath();
ctx.fillStyle = 'rgba(255,228,0,1)';
ctx.fill();
};
DragMarker.prototype.recalculatePosition = function (bounds) {
var c = bounds.getCentre();
this.setPosition(c.x, c.y);
PointPool.instance.returnPoint(c);
};
return DragMarker;
})(Handle);
var CornerMarker = (function (_super) {
__extends(CornerMarker, _super);
function CornerMarker(x, y, radius) {
_super.call(this, x, y, radius);
}
CornerMarker.prototype.drawCornerBorder = function (ctx) {
var sideLength = 10;
if (this.over || this.drag) {
sideLength = 12;
}
var hDirection = 1;
var vDirection = 1;
if (this.horizontalNeighbour.position.x < this.position.x) {
hDirection = -1;
}
if (this.verticalNeighbour.position.y < this.position.y) {
vDirection = -1;
}
ctx.beginPath();
ctx.lineJoin = "miter";
ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(this.position.x + (sideLength * hDirection), this.position.y);
ctx.lineTo(this.position.x + (sideLength * hDirection), this.position.y + (sideLength * vDirection));
ctx.lineTo(this.position.x, this.position.y + (sideLength * vDirection));
ctx.lineTo(this.position.x, this.position.y);
ctx.closePath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255,228,0,1)';
ctx.stroke();
};
CornerMarker.prototype.drawCornerFill = function (ctx) {
var sideLength = 10;
if (this.over || this.drag) {
sideLength = 12;
}
var hDirection = 1;
var vDirection = 1;
if (this.horizontalNeighbour.position.x < this.position.x) {
hDirection = -1;
}
if (this.verticalNeighbour.position.y < this.position.y) {
vDirection = -1;
}
ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(this.position.x + (sideLength * hDirection), this.position.y);
ctx.lineTo(this.position.x + (sideLength * hDirection), this.position.y + (sideLength * vDirection));
ctx.lineTo(this.position.x, this.position.y + (sideLength * vDirection));
ctx.lineTo(this.position.x, this.position.y);
ctx.closePath();
ctx.fillStyle = 'rgba(0,0,0,1)';
ctx.fill();
};
CornerMarker.prototype.moveX = function (x) {
this.setPosition(x, this.position.y);
};
CornerMarker.prototype.moveY = function (y) {
this.setPosition(this.position.x, y);
};
CornerMarker.prototype.move = function (x, y) {
this.setPosition(x, y);
this.verticalNeighbour.moveX(x);
this.horizontalNeighbour.moveY(y);
};
CornerMarker.prototype.addHorizontalNeighbour = function (neighbour) {
this.horizontalNeighbour = neighbour;
};
CornerMarker.prototype.addVerticalNeighbour = function (neighbour) {
this.verticalNeighbour = neighbour;
};
CornerMarker.prototype.getHorizontalNeighbour = function () {
return this.horizontalNeighbour;
};
CornerMarker.prototype.getVerticalNeighbour = function () {
return this.verticalNeighbour;
};
CornerMarker.prototype.draw = function (ctx) {
this.drawCornerFill(ctx);
this.drawCornerBorder(ctx);
};
return CornerMarker;
})(Handle);
var Bounds = (function () {
function Bounds(x, y, width, height) {
if (x === void 0) {
x = 0;
}
if (y === void 0) {
y = 0;
}
if (width === void 0) {
width = 0;
}
if (height === void 0) {
height = 0;
}
this.left = x;
this.right = x + width;
this.top = y;
this.bottom = y + height;
}
Bounds.prototype.getWidth = function () {
return this.right - this.left;
};
Bounds.prototype.getHeight = function () {
return this.bottom - this.top;
};
Bounds.prototype.getCentre = function () {
var w = this.getWidth();
var h = this.getHeight();
return PointPool.instance.borrow(this.left + (w / 2), this.top + (h / 2));
};
return Bounds;
})();
var Point = (function () {
function Point(x, y) {
if (x === void 0) {
x = 0;
}
if (y === void 0) {
y = 0;
}
this.x = x;
this.y = y;
}
Point.prototype.setNext = function (p) {
this.next = p;
};
Point.prototype.getNext = function () {
return this.next;
};
return Point;
})();
var CropTouch = (function () {
function CropTouch(x, y, id) {
if (x === void 0) {
x = 0;
}
if (y === void 0) {
y = 0;
}
if (id === void 0) {
id = 0;
}
this.id = 0;
this.x = x;
this.y = y;
this.id = id;
}
return CropTouch;
})();
var ImageCropper = (function () {
function ImageCropper(canvas, x, y, width, height, keepAspect, touchRadius) {
if (x === void 0) {
x = 0;
}
if (y === void 0) {
y = 0;
}
if (width === void 0) {
width = 100;
}
if (height === void 0) {
height = 50;
}
if (keepAspect === void 0) {
keepAspect = true;
}
if (touchRadius === void 0) {
touchRadius = 20;
}
this.keepAspect = false;
this.aspectRatio = 0;
this.currentDragTouches = new Array();
this.isMouseDown = false;
this.ratioW = 1;
this.ratioH = 1;
this.fileType = 'png';
this.imageSet = false;
this.pointPool = new PointPool(200);
CropService.init(canvas);
this.buffer = document.createElement('canvas');
this.cropCanvas = document.createElement('canvas');
this.buffer.width = canvas.width;
this.buffer.height = canvas.height;
this.tl = new CornerMarker(x, y, touchRadius);
this.tr = new CornerMarker(x + width, y, touchRadius);
this.bl = new CornerMarker(x, y + height, touchRadius);
this.br = new CornerMarker(x + width, y + height, touchRadius);
this.tl.addHorizontalNeighbour(this.tr);
this.tl.addVerticalNeighbour(this.bl);
this.tr.addHorizontalNeighbour(this.tl);
this.tr.addVerticalNeighbour(this.br);
this.bl.addHorizontalNeighbour(this.br);
this.bl.addVerticalNeighbour(this.tl);
this.br.addHorizontalNeighbour(this.bl);
this.br.addVerticalNeighbour(this.tr);
this.markers = [this.tl, this.tr, this.bl, this.br];
this.center = new DragMarker(x + (width / 2), y + (height / 2), touchRadius);
this.canvas = canvas;
this.ctx = this.canvas.getContext("2d");
this.keepAspect = keepAspect;
this.aspectRatio = height / width;
this.draw(this.ctx);
this.croppedImage = new Image();
this.currentlyInteracting = false;
angular.element(window)
.off('mousemove.angular-img-cropper mouseup.angular-img-cropper touchmove.angular-img-cropper touchend.angular-img-cropper')
.on('mousemove.angular-img-cropper', this.onMouseMove.bind(this))
.on('mouseup.angular-img-cropper', this.onMouseUp.bind(this))
.on('touchmove.angular-img-cropper', this.onTouchMove.bind(this))
.on('touchend.angular-img-cropper', this.onTouchEnd.bind(this));
angular.element(canvas)
.off('mousedown.angular-img-cropper touchstart.angular-img-cropper')
.on('mousedown.angular-img-cropper', this.onMouseDown.bind(this))
.on('touchstart.angular-img-cropper', this.onTouchStart.bind(this));
}
ImageCropper.prototype.resizeCanvas = function (width, height) {
this.canvas.width = width;
this.canvas.height = height;
this.buffer.width = width;
this.buffer.height = height;
this.draw(this.ctx);
};
ImageCropper.prototype.draw = function (ctx) {
var bounds = this.getBounds();
if (this.srcImage) {
ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
var sourceAspect = this.srcImage.height / this.srcImage.width;
var canvasAspect = this.canvasHeight / this.canvasWidth;
var w = this.canvasWidth;
var h = this.canvasHeight;
if (canvasAspect > sourceAspect) {
w = this.canvasWidth;
h = this.canvasWidth * sourceAspect;
}
else {
h = this.canvasHeight;
w = this.canvasHeight / sourceAspect;
}
this.ratioW = w / this.srcImage.width;
this.ratioH = h / this.srcImage.height;
if (canvasAspect < sourceAspect) {
this.drawImageIOSFix(ctx, this.srcImage, 0, 0, this.srcImage.width, this.srcImage.height, this.buffer.width / 2 - w / 2, 0, w, h);
}
else {
this.drawImageIOSFix(ctx, this.srcImage, 0, 0, this.srcImage.width, this.srcImage.height, 0, this.buffer.height / 2 - h / 2, w, h);
}
this.buffer.getContext('2d').drawImage(this.canvas, 0, 0, this.canvasWidth, this.canvasHeight);
ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
ctx.drawImage(this.buffer, bounds.left, bounds.top, Math.max(bounds.getWidth(), 1), Math.max(bounds.getHeight(), 1), bounds.left, bounds.top, bounds.getWidth(), bounds.getHeight());
var marker;
for (var i = 0; i < this.markers.length; i++) {
marker = this.markers[i];
marker.draw(ctx);
}
this.center.draw(ctx);
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255,228,0,1)';
ctx.strokeRect(bounds.left, bounds.top, bounds.getWidth(), bounds.getHeight());
}
else {
ctx.fillStyle = 'rgba(192,192,192,1)';
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
};
ImageCropper.prototype.dragCrop = function (x, y, marker) {
var bounds = this.getBounds();
var left = x - (bounds.getWidth() / 2);
var right = x + (bounds.getWidth() / 2);
var top = y - (bounds.getHeight() / 2);
var bottom = y + (bounds.getHeight() / 2);
if (right >= this.maxXClamp) {
x = this.maxXClamp - bounds.getWidth() / 2;
}
if (left <= this.minXClamp) {
x = bounds.getWidth() / 2 + this.minXClamp;
}
if (top < this.minYClamp) {
y = bounds.getHeight() / 2 + this.minYClamp;
}
if (bottom >= this.maxYClamp) {
y = this.maxYClamp - bounds.getHeight() / 2;
}
this.tl.moveX(x - (bounds.getWidth() / 2));
this.tl.moveY(y - (bounds.getHeight() / 2));
this.tr.moveX(x + (bounds.getWidth() / 2));
this.tr.moveY(y - (bounds.getHeight() / 2));
this.bl.moveX(x - (bounds.getWidth() / 2));
this.bl.moveY(y + (bounds.getHeight() / 2));
this.br.moveX(x + (bounds.getWidth() / 2));
this.br.moveY(y + (bounds.getHeight() / 2));
marker.setPosition(x, y);
if (scope.cropAreaBounds && this.imageSet) {
scope.cropAreaBounds = this.getCropBounds();
scope.$apply();
}
};
ImageCropper.prototype.enforceMinSize = function (x, y, marker) {
var xLength = x - marker.getHorizontalNeighbour().getPosition().x;
var yLength = y - marker.getVerticalNeighbour().getPosition().y;
var xOver = scope.minWidth - Math.abs(xLength);
var yOver = scope.minHeight - Math.abs(yLength);
if (xLength == 0 || yLength == 0) {
x = marker.getPosition().x;
y = marker.getPosition().y;
return PointPool.instance.borrow(x, y);
}
if(scope.keepAspect) {
if (xOver > 0 && (yOver / this.aspectRatio) > 0) {
if (xOver > (yOver / this.aspectRatio)) {
if (xLength < 0) {
x -= xOver;
if (yLength < 0) {
y -= xOver * this.aspectRatio;
}
else {
y += xOver * this.aspectRatio;
}
}
else {
x += xOver;
if (yLength < 0) {
y -= xOver * this.aspectRatio;
}
else {
y += xOver * this.aspectRatio;
}
}
}
else {
if (yLength < 0) {
y -= yOver;
if (xLength < 0) {
x -= yOver / this.aspectRatio;
}
else {
x += yOver / this.aspectRatio;
}
}
else {
y += yOver;
if (xLength < 0) {
x -= yOver / this.aspectRatio;
}
else {
x += yOver / this.aspectRatio;
}
}
}
}
else {
if (xOver > 0) {
if (xLength < 0) {
x -= xOver;
if (yLength < 0) {
y -= xOver * this.aspectRatio;
}
else {
y += xOver * this.aspectRatio;
}
}
else {
x += xOver;
if (yLength < 0) {
y -= xOver * this.aspectRatio;
}
else {
y += xOver * this.aspectRatio;
}
}
}
else if (yOver > 0) {
if (yLength < 0) {
y -= yOver;
if (xLength < 0) {
x -= yOver / this.aspectRatio;
}
else {
x += yOver / this.aspectRatio;
}
}
else {
y += yOver;
if (xLength < 0) {
x -= yOver / this.aspectRatio;
}
else {
x += yOver / this.aspectRatio;
}
}
}
}
}
else
{
if(xOver > 0)
{
if (xLength < 0) {
x -= xOver;
}
else {
x += xOver;
}
}
if(yOver > 0)
{
if (yLength < 0) {
y -= yOver;
}
else {
y += yOver;
}
}
}
if (x < this.minXClamp || x > this.maxXClamp || y < this.minYClamp || y > this.maxYClamp) {
x = marker.getPosition().x;
y = marker.getPosition().y;
}
return PointPool.instance.borrow(x, y);
};
ImageCropper.prototype.dragCorner = function (x, y, marker) {
var iX = 0;
var iY = 0;
var ax = 0;
var ay = 0;
var newHeight = 0;
var newWidth = 0;
var newY = 0;
var newX = 0;
var anchorMarker;
var fold = 0;
if (scope.keepAspect) {
anchorMarker = marker.getHorizontalNeighbour().getVerticalNeighbour();
ax = anchorMarker.getPosition().x;
ay = anchorMarker.getPosition().y;
if (x <= anchorMarker.getPosition().x) {
if (y <= anchorMarker.getPosition().y) {
iX = ax - (100 / this.aspectRatio);
iY = ay - (100 / this.aspectRatio * this.aspectRatio);
fold = this.getSide(PointPool.instance.borrow(iX, iY), anchorMarker.getPosition(), PointPool.instance.borrow(x, y));
if (fold > 0) {
newHeight = Math.abs(anchorMarker.getPosition().y - y);
newWidth = newHeight / this.aspectRatio;
newY = anchorMarker.getPosition().y - newHeight;
newX = anchorMarker.getPosition().x - newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
else if (fold < 0) {
newWidth = Math.abs(anchorMarker.getPosition().x - x);
newHeight = newWidth * this.aspectRatio;
newY = anchorMarker.getPosition().y - newHeight;
newX = anchorMarker.getPosition().x - newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
}
else {
iX = ax - (100 / this.aspectRatio);
iY = ay + (100 / this.aspectRatio * this.aspectRatio);
fold = this.getSide(PointPool.instance.borrow(iX, iY), anchorMarker.getPosition(), PointPool.instance.borrow(x, y));
if (fold > 0) {
newWidth = Math.abs(anchorMarker.getPosition().x - x);
newHeight = newWidth * this.aspectRatio;
newY = anchorMarker.getPosition().y + newHeight;
newX = anchorMarker.getPosition().x - newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
else if (fold < 0) {
newHeight = Math.abs(anchorMarker.getPosition().y - y);
newWidth = newHeight / this.aspectRatio;
newY = anchorMarker.getPosition().y + newHeight;
newX = anchorMarker.getPosition().x - newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
}
}
else {
if (y <= anchorMarker.getPosition().y) {
iX = ax + (100 / this.aspectRatio);
iY = ay - (100 / this.aspectRatio * this.aspectRatio);
fold = this.getSide(PointPool.instance.borrow(iX, iY), anchorMarker.getPosition(), PointPool.instance.borrow(x, y));
if (fold < 0) {
newHeight = Math.abs(anchorMarker.getPosition().y - y);
newWidth = newHeight / this.aspectRatio;
newY = anchorMarker.getPosition().y - newHeight;
newX = anchorMarker.getPosition().x + newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
else if (fold > 0) {
newWidth = Math.abs(anchorMarker.getPosition().x - x);
newHeight = newWidth * this.aspectRatio;
newY = anchorMarker.getPosition().y - newHeight;
newX = anchorMarker.getPosition().x + newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
}
else {
iX = ax + (100 / this.aspectRatio);
iY = ay + (100 / this.aspectRatio * this.aspectRatio);
fold = this.getSide(PointPool.instance.borrow(iX, iY), anchorMarker.getPosition(), PointPool.instance.borrow(x, y));
if (fold < 0) {
newWidth = Math.abs(anchorMarker.getPosition().x - x);
newHeight = newWidth * this.aspectRatio;
newY = anchorMarker.getPosition().y + newHeight;
newX = anchorMarker.getPosition().x + newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
else if (fold > 0) {
newHeight = Math.abs(anchorMarker.getPosition().y - y);
newWidth = newHeight / this.aspectRatio;
newY = anchorMarker.getPosition().y + newHeight;
newX = anchorMarker.getPosition().x + newWidth;
var min = this.enforceMinSize(newX, newY, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
}
}
}
else {
var min = this.enforceMinSize(x, y, marker);
marker.move(min.x, min.y);
PointPool.instance.returnPoint(min);
}
this.center.recalculatePosition(this.getBounds());
if (scope.cropAreaBounds && this.imageSet) {
scope.cropAreaBounds = this.getCropBounds();
scope.$apply();
}
};
ImageCropper.prototype.getSide = function (a, b, c) {
var n = this.sign((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x));
//TODO move the return of the pools to outside of this function
PointPool.instance.returnPoint(a);
PointPool.instance.returnPoint(c);
return n;
};
ImageCropper.prototype.sign = function (x) {
if (+x === x) {
return (x === 0) ? x : (x > 0) ? 1 : -1;
}
return NaN;
};
ImageCropper.prototype.handleRelease = function (newCropTouch) {
if (newCropTouch == null) {
return;
}
var index = 0;
for (var k = 0; k < this.currentDragTouches.length; k++) {
if (newCropTouch.id == this.currentDragTouches[k].id) {
this.currentDragTouches[k].dragHandle.setDrag(false);
newCropTouch.dragHandle = null;
index = k;
}
}
this.currentDragTouches.splice(index, 1);
this.draw(this.ctx);
};
ImageCropper.prototype.handleMove = function (newCropTouch) {
var matched = false;
for (var k = 0; k < this.currentDragTouches.length; k++) {
if (newCropTouch.id == this.currentDragTouches[k].id && this.currentDragTouches[k].dragHandle != null) {
var dragTouch = this.currentDragTouches[k];
var clampedPositions = this.clampPosition(newCropTouch.x - dragTouch.dragHandle.offset.x, newCropTouch.y - dragTouch.dragHandle.offset.y);
newCropTouch.x = clampedPositions.x;
newCropTouch.y = clampedPositions.y;
PointPool.instance.returnPoint(clampedPositions);
if (dragTouch.dragHandle instanceof CornerMarker) {
this.dragCorner(newCropTouch.x, newCropTouch.y, dragTouch.dragHandle);
}
else {
this.dragCrop(newCropTouch.x, newCropTouch.y, dragTouch.dragHandle);
}
this.currentlyInteracting = true;
matched = true;
imageCropperDataShare.setPressed(this.canvas);
break;
}
}
if (!matched) {
for (var i = 0; i < this.markers.length; i++) {
var marker = this.markers[i];
if (marker.touchInBounds(newCropTouch.x, newCropTouch.y)) {
newCropTouch.dragHandle = marker;
this.currentDragTouches.push(newCropTouch);
marker.setDrag(true);
newCropTouch.dragHandle.offset.x = newCropTouch.x - newCropTouch.dragHandle.getPosition().x;
newCropTouch.dragHandle.offset.y = newCropTouch.y - newCropTouch.dragHandle.getPosition().y;
this.dragCorner(newCropTouch.x - newCropTouch.dragHandle.offset.x, newCropTouch.y - newCropTouch.dragHandle.offset.y, newCropTouch.dragHandle);
break;
}
}
if (newCropTouch.dragHandle == null) {
if (this.center.touchInBounds(newCropTouch.x, newCropTouch.y)) {
newCropTouch.dragHandle = this.center;
this.currentDragTouches.push(newCropTouch);
newCropTouch.dragHandle.setDrag(true);
newCropTouch.dragHandle.offset.x = newCropTouch.x - newCropTouch.dragHandle.getPosition().x;
newCropTouch.dragHandle.offset.y = newCropTouch.y - newCropTouch.dragHandle.getPosition().y;
this.dragCrop(newCropTouch.x - newCropTouch.dragHandle.offset.x, newCropTouch.y - newCropTouch.dragHandle.offset.y, newCropTouch.dragHandle);
}
}
}
};
ImageCropper.prototype.updateClampBounds = function () {
var sourceAspect = this.srcImage.height / this.srcImage.width;
var canvasAspect = this.canvas.height / this.canvas.width;
var w = this.canvas.width;
var h = this.canvas.height;
if (canvasAspect > sourceAspect) {
w = this.canvas.width;
h = this.canvas.width * sourceAspect;
}
else {
h = this.canvas.height;
w = this.canvas.height / sourceAspect;
}
this.minXClamp = this.canvas.width / 2 - w / 2;
this.minYClamp = this.canvas.height / 2 - h / 2;
this.maxXClamp = this.canvas.width / 2 + w / 2;
this.maxYClamp = this.canvas.height / 2 + h / 2;
};
ImageCropper.prototype.getCropBounds = function () {
var h = this.canvas.height - (this.minYClamp * 2);
var bounds = this.getBounds();
bounds.top = Math.round((h - bounds.top + this.minYClamp) / this.ratioH);
bounds.bottom = Math.round((h - bounds.bottom + this.minYClamp) / this.ratioH);
bounds.left = Math.round((bounds.left - this.minXClamp) / this.ratioW);
bounds.right = Math.round((bounds.right - this.minXClamp) / this.ratioW);
return bounds;
};
ImageCropper.prototype.clampPosition = function (x, y) {
if (x < this.minXClamp) {
x = this.minXClamp;
}
if (x > this.maxXClamp) {
x = this.maxXClamp;
}
if (y < this.minYClamp) {
y = this.minYClamp;
}
if (y > this.maxYClamp) {
y = this.maxYClamp;
}
return PointPool.instance.borrow(x, y);
};
ImageCropper.prototype.isImageSet = function () {
return this.imageSet;
};
ImageCropper.prototype.setImage = function (img) {
if (!img) {
throw "Image is null";
}
this.imageSet = true;
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
var bufferContext = this.buffer.getContext('2d');
bufferContext.clearRect(0, 0, this.buffer.width, this.buffer.height);
var splitName = img.src.split('.');
var fileType = splitName[1];
if (fileType == 'png' || fileType == 'jpg') {
this.fileType = fileType;
}
this.srcImage = img;
this.updateClampBounds();
var sourceAspect = this.srcImage.height / this.srcImage.width;
var cropBounds = this.getBounds();
var cropAspect = cropBounds.getHeight() / cropBounds.getWidth();
var w = this.canvas.width;
var h = this.canvas.height;
this.canvasWidth = w;
this.canvasHeight = h;
var cX = this.canvas.width / 2;
var cY = this.canvas.height / 2;
var tlPos = PointPool.instance.borrow(cX - cropBounds.getWidth() / 2, cY + cropBounds.getHeight() / 2);
var trPos = PointPool.instance.borrow(cX + cropBounds.getWidth() / 2, cY + cropBounds.getHeight() / 2);
var blPos = PointPool.instance.borrow(cX - cropBounds.getWidth() / 2, cY - cropBounds.getHeight() / 2);
var brPos = PointPool.instance.borrow(cX + cropBounds.getWidth() / 2, cY - cropBounds.getHeight() / 2);
this.tl.setPosition(tlPos.x, tlPos.y);
this.tr.setPosition(trPos.x, trPos.y);
this.bl.setPosition(blPos.x, blPos.y);
this.br.setPosition(brPos.x, brPos.y);
PointPool.instance.returnPoint(tlPos);
PointPool.instance.returnPoint(trPos);
PointPool.instance.returnPoint(blPos);
PointPool.instance.returnPoint(brPos);
this.center.setPosition(cX, cY);
if (cropAspect > sourceAspect) {
var imageH = Math.min(w * sourceAspect, h);
var cropW = imageH / cropAspect;
tlPos = PointPool.instance.borrow(cX - cropW / 2, cY + imageH / 2);
trPos = PointPool.instance.borrow(cX + cropW / 2, cY + imageH / 2);
blPos = PointPool.instance.borrow(cX - cropW / 2, cY - imageH / 2);
brPos = PointPool.instance.borrow(cX + cropW / 2, cY - imageH / 2);
} else if (cropAspect < sourceAspect) {
var imageW = Math.min(h / sourceAspect, w);
var cropH = imageW * cropAspect;
tlPos = PointPool.instance.borrow(cX - imageW / 2, cY + cropH / 2);
trPos = PointPool.instance.borrow(cX + imageW / 2, cY + cropH / 2);
blPos = PointPool.instance.borrow(cX - imageW / 2, cY - cropH / 2);
brPos = PointPool.instance.borrow(cX + imageW / 2, cY - cropH / 2);
} else {
var imageW = Math.min(h, w);
var cropH = imageW * cropAspect;
tlPos = PointPool.instance.borrow(cX - imageW / 2, cY + cropH / 2);
trPos = PointPool.instance.borrow(cX + imageW / 2, cY + cropH / 2);
blPos = PointPool.instance.borrow(cX - imageW / 2, cY - cropH / 2);
brPos = PointPool.instance.borrow(cX + imageW / 2, cY - cropH / 2);
}
this.tl.setPosition(tlPos.x, tlPos.y);
this.tr.setPosition(trPos.x, trPos.y);
this.bl.setPosition(blPos.x, blPos.y);
this.br.setPosition(brPos.x, brPos.y);
PointPool.instance.returnPoint(tlPos);
PointPool.instance.returnPoint(trPos);
PointPool.instance.returnPoint(blPos);
PointPool.instance.returnPoint(brPos);
if(scope.cropAreaBounds
&& scope.cropAreaBounds.left !== undefined
&& scope.cropAreaBounds.top !== undefined
&& scope.cropAreaBounds.right !== undefined
&& scope.cropAreaBounds.bottom !== undefined) {
var canvasAspect = this.canvasHeight / this.canvasWidth;
if (canvasAspect > sourceAspect) {
w = this.canvasWidth;
h = this.canvasWidth * sourceAspect;
} else {
h = this.canvasHeight;
w = this.canvasHeight / sourceAspect;
}
this.ratioW = w / this.srcImage.width;
this.ratioH = h / this.srcImage.height;
var bounds = new Bounds();
bounds.top = Math.round(h + this.minYClamp - this.ratioH*scope.cropAreaBounds.top);
bounds.bottom = Math.round(h + this.minYClamp - this.ratioH*scope.cropAreaBounds.bottom);
bounds.left = Math.round(this.ratioW*scope.cropAreaBounds.left + this.minXClamp);
bounds.right = Math.round(this.ratioW*scope.cropAreaBounds.right + this.minXClamp);
this.tl.setPosition(bounds.left, bounds.top);
this.tr.setPosition(bounds.right, bounds.top);
this.bl.setPosition(bounds.left, bounds.bo