Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

non-square selections #1

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b919ac9
add support for cropped image data (pixel array from canvas's 2D cont…
chirgwin Jul 27, 2014
a1a700f
prepare for non-square selection areas; refactor bounds to use northw…
chirgwin Jul 28, 2014
680558e
finish implementing canvas boundary collision checking; swap draw cro…
chirgwin Jul 29, 2014
f377700
allow size of square-like areas (width equals height) to be set with …
chirgwin Jul 29, 2014
e2d3833
simplify square corners/dimensions calculations
chirgwin Jul 29, 2014
d1b37d6
first cut of rectangular selections, where each corner can be dragged…
chirgwin Jul 29, 2014
24eee4a
use canvas/size height properties when preventing dragging outside ou…
chirgwin Jul 29, 2014
48517e1
use actual selection size for size of generated image
chirgwin Jul 29, 2014
ed1a87b
allow result image size to be configurable (this was removed in previ…
chirgwin Jul 29, 2014
e11cec8
fix up type checking in result image size setter
chirgwin Jul 30, 2014
5931b1f
return an object containing null values and do not attempt to get ima…
chirgwin Jul 30, 2014
86af704
simplify boundary collisions between selection and canvas; prevent re…
chirgwin Aug 8, 2014
b36fc1b
correct typo/bug in canvas height check; do not check boundaries when…
chirgwin Aug 8, 2014
4ce543f
Merge remote-tracking branch 'upstream/master'
chirgwin Aug 17, 2014
be414c2
remove calls to method already removed from crop-area class; geometry…
chirgwin Aug 17, 2014
8a79998
enforce intial 1:1 selection aspect ratio for square & circle selecti…
chirgwin Aug 17, 2014
54abd96
refactor area type checking to use new getter method rather than pass…
chirgwin Aug 17, 2014
3b180dc
* refactor area type getter down to area classes, with a wrapper meth…
chirgwin Aug 17, 2014
85774a5
Introduced aspectRatio parameter for Rectangle Area
Sep 15, 2014
22ad364
Updated documentation for aspect ratio parameter
Sep 15, 2014
0f45f26
Fixed bug for result image size to resize according to crop selection
Sep 15, 2014
3cf42b4
Updated compiled files
Sep 15, 2014
db13298
Merge pull request #1 from sderungs/master
chirgwin Sep 15, 2014
62614d5
add test page referenced in gulp configuration
chirgwin Nov 17, 2014
68e9e39
revert buggy pixel array image data property from commit b919ac94e5
chirgwin Nov 17, 2014
91a28a0
remove test page
chirgwin Nov 18, 2014
f1c6777
Revert "Introduced aspect ratio parameter for rectangle area"
chirgwin Dec 9, 2014
c985ea2
Merge pull request #2 from PortChaw/revert-1-master
chirgwin Dec 9, 2014
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
44 changes: 28 additions & 16 deletions source/js/classes/crop-area-circle.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {
this._posDragStartY=0;
this._posResizeStartX=0;
this._posResizeStartY=0;
this._posResizeStartSize=0;
this._posResizeStartSize={w: 0, h: 0};

this._boxResizeIsHover = false;
this._areaIsHover = false;
Expand All @@ -27,11 +27,17 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {

CropAreaCircle.prototype = new CropArea();

// return a type string
CropAreaCircle.prototype.getType = function() {
return 'circle';
}

CropAreaCircle.prototype._calcCirclePerimeterCoords=function(angleDegrees) {
var hSize=this._size/2;
var c = this.getCenterPoint();
var s = this.getSize();
var angleRadians=angleDegrees * (Math.PI / 180),
circlePerimeterX=this._x + hSize * Math.cos(angleRadians),
circlePerimeterY=this._y + hSize * Math.sin(angleRadians);
circlePerimeterX=c.x + s.w / 2 * Math.cos(angleRadians),
circlePerimeterY=c.y + s.h / 2 * Math.sin(angleRadians);
return [circlePerimeterX, circlePerimeterY];
};

Expand All @@ -40,7 +46,8 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {
};

CropAreaCircle.prototype._isCoordWithinArea=function(coord) {
return Math.sqrt((coord[0]-this._x)*(coord[0]-this._x) + (coord[1]-this._y)*(coord[1]-this._y)) < this._size/2;
var c = this.getCenterPoint();
return Math.sqrt((coord[0]-c.x)*(coord[0]-c.x) + (coord[1]-c.y)*(coord[1]-c.y)) < this._size.h/2;
};
CropAreaCircle.prototype._isCoordWithinBoxResize=function(coord) {
var resizeIconCenterCoords=this._calcResizeIconCenterCoords();
Expand All @@ -49,15 +56,16 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {
coord[1] > resizeIconCenterCoords[1] - hSize && coord[1] < resizeIconCenterCoords[1] + hSize);
};

CropAreaCircle.prototype._drawArea=function(ctx,centerCoords,size){
ctx.arc(centerCoords[0],centerCoords[1],size/2,0,2*Math.PI);
CropAreaCircle.prototype._drawArea=function(ctx, center, size){
ctx.arc(center.x, center.y,size.h/2,0,2*Math.PI);
};

CropAreaCircle.prototype.draw=function() {
CropArea.prototype.draw.apply(this, arguments);

// draw move icon
this._cropCanvas.drawIconMove([this._x,this._y], this._areaIsHover?this._iconMoveHoverRatio:this._iconMoveNormalRatio);
var c = this.getCenterPoint();
this._cropCanvas.drawIconMove([c.x, c.y], this._areaIsHover?this._iconMoveHoverRatio:this._iconMoveNormalRatio);

// draw resize cubes
this._cropCanvas.drawIconResizeBoxNESW(this._calcResizeIconCenterCoords(), this._boxResizeBaseSize, this._boxResizeIsHover?this._boxResizeHoverRatio:this._boxResizeNormalRatio);
Expand All @@ -71,8 +79,7 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {
this._areaIsHover = false;

if (this._areaIsDragging) {
this._x = mouseCurX - this._posDragStartX;
this._y = mouseCurY - this._posDragStartY;
this.setCenterPoint({x: mouseCurX - this._posDragStartX, y: mouseCurY - this._posDragStartY});
this._areaIsHover = true;
cursor='move';
res=true;
Expand All @@ -83,12 +90,18 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {
iFX = mouseCurX - this._posResizeStartX;
iFY = this._posResizeStartY - mouseCurY;
if(iFX>iFY) {
iFR = this._posResizeStartSize + iFY*2;
iFR = this._posResizeStartSize.h + iFY*2;
} else {
iFR = this._posResizeStartSize + iFX*2;
iFR = this._posResizeStartSize.w + iFX*2;
}

this._size = Math.max(this._minSize, iFR);
var prevCenter = this.getCenterPoint();

this.setSize(Math.max(this._minSize.h, iFR));

//recenter
this.setCenterPoint(prevCenter);

this._boxResizeIsHover = true;
res=true;
this._events.trigger('area-resize');
Expand All @@ -103,7 +116,6 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {
res=true;
}

this._dontDragOutside();
angular.element(this._ctx.canvas).css({'cursor': cursor});

return res;
Expand All @@ -124,8 +136,8 @@ crop.factory('cropAreaCircle', ['cropArea', function(CropArea) {
this._areaIsHover = true;
this._boxResizeIsDragging = false;
this._boxResizeIsHover = false;
this._posDragStartX = mouseDownX - this._x;
this._posDragStartY = mouseDownY - this._y;
this._posDragStartX = mouseDownX - this.getCenterPoint().x;
this._posDragStartY = mouseDownY - this.getCenterPoint().y;
this._events.trigger('area-move-start');
}
};
Expand Down
207 changes: 207 additions & 0 deletions source/js/classes/crop-area-rectangle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
'use strict';

crop.factory('cropAreaRectangle', ['cropArea', function(CropArea) {
var CropAreaRectangle = function() {
CropArea.apply(this, arguments);

this._resizeCtrlBaseRadius = 10;
this._resizeCtrlNormalRatio = 0.75;
this._resizeCtrlHoverRatio = 1;
this._iconMoveNormalRatio = 0.9;
this._iconMoveHoverRatio = 1.2;

this._resizeCtrlNormalRadius = this._resizeCtrlBaseRadius*this._resizeCtrlNormalRatio;
this._resizeCtrlHoverRadius = this._resizeCtrlBaseRadius*this._resizeCtrlHoverRatio;

this._posDragStartX=0;
this._posDragStartY=0;
this._posResizeStartX=0;
this._posResizeStartY=0;
this._posResizeStartSize={w: 0, h: 0};

this._resizeCtrlIsHover = -1;
this._areaIsHover = false;
this._resizeCtrlIsDragging = -1;
this._areaIsDragging = false;
};

CropAreaRectangle.prototype = new CropArea();

// return a type string
CropAreaRectangle.prototype.getType = function() {
return 'rectangle';
}

CropAreaRectangle.prototype._calcRectangleCorners=function() {
var size = this.getSize();
var se = this.getSouthEastBound();
return [
[size.x, size.y], //northwest
[se.x, size.y], //northeast
[size.x, se.y], //southwest
[se.x, se.y] //southeast
];
};

CropAreaRectangle.prototype._calcRectangleDimensions=function() {
var size = this.getSize();
var se = this.getSouthEastBound();
return {
left: size.x,
top: size.y,
right: se.x,
bottom: se.y
};
};

CropAreaRectangle.prototype._isCoordWithinArea=function(coord) {
var rectangleDimensions=this._calcRectangleDimensions();
return (coord[0]>=rectangleDimensions.left&&coord[0]<=rectangleDimensions.right&&coord[1]>=rectangleDimensions.top&&coord[1]<=rectangleDimensions.bottom);
};

CropAreaRectangle.prototype._isCoordWithinResizeCtrl=function(coord) {
var resizeIconsCenterCoords=this._calcRectangleCorners();
var res=-1;
for(var i=0,len=resizeIconsCenterCoords.length;i<len;i++) {
var resizeIconCenterCoords=resizeIconsCenterCoords[i];
if(coord[0] > resizeIconCenterCoords[0] - this._resizeCtrlHoverRadius && coord[0] < resizeIconCenterCoords[0] + this._resizeCtrlHoverRadius &&
coord[1] > resizeIconCenterCoords[1] - this._resizeCtrlHoverRadius && coord[1] < resizeIconCenterCoords[1] + this._resizeCtrlHoverRadius) {
res=i;
break;
}
}
return res;
};

CropAreaRectangle.prototype._drawArea=function(ctx,center,size){
ctx.rect(size.x,size.y,size.w,size.h);
};

CropAreaRectangle.prototype.draw=function() {
CropArea.prototype.draw.apply(this, arguments);

var center=this.getCenterPoint();
// draw move icon
this._cropCanvas.drawIconMove([center.x, center.y], this._areaIsHover?this._iconMoveHoverRatio:this._iconMoveNormalRatio);

// draw resize thumbs
var resizeIconsCenterCoords=this._calcRectangleCorners();
for(var i=0,len=resizeIconsCenterCoords.length;i<len;i++) {
var resizeIconCenterCoords=resizeIconsCenterCoords[i];
this._cropCanvas.drawIconResizeCircle(resizeIconCenterCoords, this._resizeCtrlBaseRadius, this._resizeCtrlIsHover===i?this._resizeCtrlHoverRatio:this._resizeCtrlNormalRatio);
}
};

CropAreaRectangle.prototype.processMouseMove=function(mouseCurX, mouseCurY) {
var cursor='default';
var res=false;

this._resizeCtrlIsHover = -1;
this._areaIsHover = false;

if (this._areaIsDragging) {
this.setCenterPoint({x: mouseCurX - this._posDragStartX,
y: mouseCurY - this._posDragStartY});
this._areaIsHover = true;
cursor='move';
res=true;
this._events.trigger('area-move');
} else if (this._resizeCtrlIsDragging>-1) {
var s = this.getSize();
var se = this.getSouthEastBound();
switch(this._resizeCtrlIsDragging) {
case 0: // Top Left
this.setSizeByCorners({x: mouseCurX, y: mouseCurY}, {x: se.x, y: se.y});
cursor = 'nwse-resize';
break;
case 1: // Top Right
this.setSizeByCorners({x: s.x, y: mouseCurY}, {x: mouseCurX, y: se.y});
cursor = 'nesw-resize';
break;
case 2: // Bottom Left
this.setSizeByCorners({x: mouseCurX, y: s.y}, {x: se.x, y: mouseCurY});
cursor = 'nesw-resize';
break;
case 3: // Bottom Right
this.setSizeByCorners({x: s.x, y: s.y}, {x: mouseCurX, y: mouseCurY});
cursor = 'nwse-resize';
break;
}

this._resizeCtrlIsHover = this._resizeCtrlIsDragging;
res=true;
this._events.trigger('area-resize');
} else {
var hoveredResizeBox=this._isCoordWithinResizeCtrl([mouseCurX,mouseCurY]);
if (hoveredResizeBox>-1) {
switch(hoveredResizeBox) {
case 0:
cursor = 'nwse-resize';
break;
case 1:
cursor = 'nesw-resize';
break;
case 2:
cursor = 'nesw-resize';
break;
case 3:
cursor = 'nwse-resize';
break;
}
this._areaIsHover = false;
this._resizeCtrlIsHover = hoveredResizeBox;
res=true;
} else if(this._isCoordWithinArea([mouseCurX,mouseCurY])) {
cursor = 'move';
this._areaIsHover = true;
res=true;
}
}

angular.element(this._ctx.canvas).css({'cursor': cursor});

return res;
};

CropAreaRectangle.prototype.processMouseDown=function(mouseDownX, mouseDownY) {
var isWithinResizeCtrl=this._isCoordWithinResizeCtrl([mouseDownX,mouseDownY]);
if (isWithinResizeCtrl>-1) {
this._areaIsDragging = false;
this._areaIsHover = false;
this._resizeCtrlIsDragging = isWithinResizeCtrl;
this._resizeCtrlIsHover = isWithinResizeCtrl;
this._posResizeStartX=mouseDownX;
this._posResizeStartY=mouseDownY;
this._posResizeStartSize = this._size;
this._events.trigger('area-resize-start');
} else if (this._isCoordWithinArea([mouseDownX,mouseDownY])) {
this._areaIsDragging = true;
this._areaIsHover = true;
this._resizeCtrlIsDragging = -1;
this._resizeCtrlIsHover = -1;
var center = this.getCenterPoint();
this._posDragStartX = mouseDownX - center.x;
this._posDragStartY = mouseDownY - center.y;
this._events.trigger('area-move-start');
}
};

CropAreaRectangle.prototype.processMouseUp=function(/*mouseUpX, mouseUpY*/) {
if(this._areaIsDragging) {
this._areaIsDragging = false;
this._events.trigger('area-move-end');
}
if(this._resizeCtrlIsDragging>-1) {
this._resizeCtrlIsDragging = -1;
this._events.trigger('area-resize-end');
}
this._areaIsHover = false;
this._resizeCtrlIsHover = -1;

this._posDragStartX = 0;
this._posDragStartY = 0;
};


return CropAreaRectangle;
}]);
Loading