Rect
Object
The
Rect
class is the heart of the Jcrop engine. While it may appear to be a plain old Javascript object, it has some unique behavior that makes it easy to work with coordinates and crop selections.
A Rect
object instance represents coordinates for an arbitrary
rectangle, usually top left and bottom right. Internally the class
is used to set or describe an existing crop selection. You may
use Rect
objects when using the Jcrop API or to describe rectangles
within your own application.
Properties
The native properties of a Rect
object are x
, y
, w
, h
. These
properties should only contain integers or floating point numbers that
represent the x
and y
top left corner of the crop, and the crop
dimentions as w
and h
for width and height, respectively.
Getters and setters exist for x2
and y2
, if it is desirable to
know the secondary coordinates (usually the bottom-right point). If
you set x2
or y2
, the object's w
and h
values are updated as
if the secondary point had been moved.
Additionally, x1
and y1
setters exist for cases where you want
to move the primary point without without moving the entire object.
Another way to say this is that w
and h
will be adjusted as if
only this point moved.
To get the aspect ratio of the Rect
object's current values,
a getter named aspect
exists.
Instance Methods
rect.normalize()
Rect coordinates may have negative values for w
or h
if the
secondary point is above or to the left of the primary point.
Calling the normalize()
method will return a new Rect
object
with adjusted values indicating a positive w
and h
. This method
is used internally by Jcrop to provide values that are easily
rendered regardless of the current orientation of the coordinates,
such as during a dragging operation.
const r = Jcrop.Rect.create(110,110,-100,-50);
const s = r.normalize();
console.log(r.x,r.w); // --> 110, -100
console.log(s.x,s.w); // --> 10, 100
rect.rebound(w,h)
The rebound()
method will move the Rect coordinates back into an
area inside of a box defined by the w,h parameters given. It returns
a Rect
object with the rebounded coordinates. This method is used
internally to prevent a bounded crop from being dragged outside the
boundaries of the stage element.
const r = Jcrop.Rect.create(-15,-20,100,50);
const s = r.rebound(200,200);
console.log(r.x,r.y); // --> -15, -20
console.log(s.x,s.y); // --> 0, 0
rect.scale(x,y)
Scales the width and height based on x,y
scaling values,
usually somewhere between 1 and 0 for a percentage. Returns a
fresh Rect
object with the width and height scaled.
rect.center(w,h)
Returns a new Rect
object with x,y
producing a region
centered within the space defined by w,h
.
rect.round()
Especially when using aspect ratios, fractional values are very
possible, but not always desirable. Call the round()
method and
get a totally new Rect
with rounded values.
Static Methods
Rect.create(x,y,w,h)
Creates a new Rect
object with the given values.
const r = Jcrop.Rect.create(10,10,100,100);
Rect.from(el)
Creates a new Rect
object by reading offsetTop
, offsetLeft
,
offsetWidth
and offsetHeight
from the given DOM object. The
object should probably be in the DOM, as not all of these properties
may be set on an element that is not in the DOM.
const el = document.getElementById('crop1');
const r = Jcrop.Rect.from(el);
Rect.fromPoints(p1,p2)
Creates a new Rect
from coordinate points specified as arrays
(e.g. [x1,y1]
and [x2,y2]
).
const p1 = [10,10], p2 = [110,110];
const r = Jcrop.Rect.fromPoints(p1,p2);
Rect.fromPoint(p1,w,h,quad)
Creates a new Rect
object anchored at a single point, such as [10,10]
.
The Rect will be of size w
and h
and the direction is determined
by the value of quad
which must be one of tl
, tr
, bl
, or br
(the default) indicating top/bottom left/right quadrant.
const point = [10,10];
const r = Jcrop.Rect.fromPoint(point,100,100,'br');
Rect.getMax(w,h,aspect)
Returns an array of [w,h]
representing maximum rectangle size
of ratio
that fits within the given w,h
size passed as parameters.
This function is used in conjunction with Rect.fromPoint()
to
perform aspect ratio filtering when that feature is enabled.
const ratio = 4/3;
const [w,h] = Jcrop.Rect.getMax(200,150,ratio);
Source Code
/* Rect class -- describes a rectangle with two points, usually
top left and bottom right. It allows the second set of coordinates
to be described as either w/h or x2/y2 and allows getting and
setting of those values such that the object values will always be
consistent with the latest input. It should be noted that it does not
attempt to keep these points normalized. That is, you should expect
to see the actual w/h properties to sometimes be negative values.
To normalize the values, use the normalize method, which will return
a new Rect object with normalized values.
*/
class Rect {
constructor () {
this.x = 0;
this.y = 0;
this.w = 0;
this.h = 0;
}
set x1 (v) {
this.w = this.x2 - v;
this.x = v;
}
set y1 (v) {
this.h = this.y2 - v;
this.y = v;
}
get x2 () {
return this.x + this.w;
}
set x2 (x) {
this.w = x - this.x;
}
get y2 () {
return this.y + this.h;
}
get aspect () {
return this.w/this.h;
}
set y2 (y) {
this.h = y - this.y;
}
round () {
return Rect.create(
Math.round(this.x),
Math.round(this.y),
Math.round(this.w),
Math.round(this.h)
);
}
normalize () {
const [x1,y1,x2,y2] = [
Math.min(this.x,this.x2),
Math.min(this.y,this.y2),
Math.max(this.x,this.x2),
Math.max(this.y,this.y2)
];
return Rect.create(x1,y1,x2-x1,y2-y1);
}
rebound (w,h) {
const rect = this.normalize();
if (rect.x<0) rect.x = 0;
if (rect.y<0) rect.y = 0;
if (rect.x2>w) rect.x = w-rect.w;
if (rect.y2>h) rect.y = h-rect.h;
return rect;
}
scale (x,y) {
y = y || x;
return Rect.create(this.x*x,this.y*y,this.w*x,this.h*y);
}
unscale (x,y) {
y = y || x;
return Rect.create(this.x/x,this.y/y,this.w/x,this.h/y);
}
center (w,h) {
return Rect.create(
(w - this.w)/2,
(h - this.h)/2,
this.w, this.h
);
}
toArray () {
return [ this.x, this.y, this.w, this.h ];
}
}
Rect.fromPoints = function (p1,p2) {
const [x1,y1,x2,y2] = [
Math.min(p1[0],p2[0]),
Math.min(p1[1],p2[1]),
Math.max(p1[0],p2[0]),
Math.max(p1[1],p2[1])
];
return Rect.create(x1,y1,x2-x1,y2-y1);
};
Rect.create = function (x=0,y=0,w=0,h=0) {
const c = new Rect();
c.x = x;
c.y = y;
c.w = w;
c.h = h;
return c;
};
Rect.from = function (el) {
if (Array.isArray(el)) return Rect.fromArray(el);
const c = new Rect();
c.x = el.offsetLeft;
c.y = el.offsetTop;
c.w = el.offsetWidth;
c.h = el.offsetHeight;
return c;
};
Rect.fromArray = function (args) {
if (args.length === 4) return Rect.create.apply(this,args);
else if (args.length === 2) return Rect.fromPoints(args[0],args[1]);
else throw new Error('fromArray method problem');
};
Rect.sizeOf = function (el,y) {
if (y) return Rect.create(0,0,el,y);
const c = new Rect();
c.w = el.offsetWidth;
c.h = el.offsetHeight;
return c;
};
Rect.getMax = function (w,h,aspect) {
if ((w/h) > aspect) return [ h*aspect, h ];
else return [ w, w/aspect ];
};
Rect.fromPoint = function (point,w,h,quad='br') {
const c = new Rect();
c.x = point[0];
c.y = point[1];
switch (quad) {
case 'br':
c.x2 = c.x + w;
c.y2 = c.y + h;
break;
case 'bl':
c.x2 = c.x - w;
c.y2 = c.y + h;
break;
case 'tl':
c.x2 = c.x - w;
c.y2 = c.y - h;
break;
case 'tr':
c.x2 = c.x + w;
c.y2 = c.y - h;
break;
}
return c;
};
export default Rect;