@dominicstop/utils
Version:
Yet another event emitter written in typescript.
327 lines (326 loc) • 8.13 kB
JavaScript
import { Point } from "./Point";
export class Rect {
constructor(args) {
switch (args.mode) {
case 'originAndSize':
this.origin = new Point(args.origin);
this.size = args.size;
break;
case 'corners':
this.origin = new Point({
x: args.minX,
y: args.minY
});
this.size = {
width: args.maxX - args.minX,
height: args.maxY - args.minY
};
break;
default:
this.origin = Point.zero;
this.size = { width: 0, height: 0 };
break;
}
;
}
;
;
// MARK: Getter + Setter
// ---------------------
get minX() {
return this.origin.x;
}
;
set minX(value) {
this.origin.x = value;
}
;
get minY() {
return this.origin.y;
}
;
set minY(value) {
this.origin.y = value;
}
;
get midX() {
return this.origin.x + (this.size.width / 2);
}
;
set midX(value) {
this.origin.x = value - (this.width / 2);
}
;
get midY() {
return this.origin.y + (this.size.height / 2);
}
;
set midY(value) {
this.origin.y = value - (this.height / 2);
}
;
get maxX() {
return this.origin.x + this.size.width;
}
;
set maxX(value) {
this.origin.x = value - this.width;
}
;
get maxY() {
return this.origin.y + this.size.height;
}
;
set maxY(value) {
this.origin.y = value - this.height;
}
;
// MARK: Computed Properties
// -------------------------
get asValue() {
return {
origin: this.origin,
size: this.size,
};
}
;
get boundingBox() {
return new Rect({
mode: 'originAndSize',
...this.asValue,
});
}
;
get width() {
return this.size.width;
}
;
get height() {
return this.size.height;
}
;
get isNaN() {
return (Number.isNaN(this.origin.x)
|| Number.isNaN(this.origin.y)
|| Number.isNaN(this.size.width)
|| Number.isNaN(this.size.height));
}
;
get area() {
return this.width * this.height;
}
;
// MARK: Computed Properties - Points
// ----------------------------------
get minMaxDimensions() {
return {
minX: this.minX,
minY: this.minY,
maxX: this.maxX,
maxY: this.maxY,
};
}
;
get center() {
return new Point({
x: this.midX,
y: this.midY
});
}
;
get topMidPoint() {
return new Point({
x: this.midX,
y: this.minY
});
}
;
get bottomMidPoint() {
return new Point({
x: this.midX,
y: this.maxY
});
}
;
get leftMidPoint() {
return new Point({
x: this.minX,
y: this.midY
});
}
;
get rightMidPoint() {
return new Point({
x: this.maxX,
y: this.midY
});
}
;
get topLeftPoint() {
return new Point({
x: this.minX,
y: this.minY
});
}
;
get topRightPoint() {
return new Point({
x: this.maxX,
y: this.minY
});
}
get bottomLeftPoint() {
return new Point({
x: this.minX,
y: this.maxY
});
}
get bottomRightPoint() {
return new Point({
x: this.maxX,
y: this.maxY
});
}
;
get cornerPointsAsArray() {
return [
this.topLeftPoint,
this.topRightPoint,
this.bottomLeftPoint,
this.bottomRightPoint,
];
}
;
// MARK: Methods
// -------------
clone() {
return new Rect({
mode: 'originAndSize',
origin: this.origin,
size: this.size,
});
}
;
computeDistanceToOther(other) {
return this.center.getDistance(other.center);
}
;
isPointInside(pointValue) {
const { x, y } = pointValue;
return (x >= this.minX &&
x <= this.maxX &&
y >= this.minY &&
y <= this.maxY);
}
isEdgeToEdgeWithOther(other) {
return (this.maxX === other.minX || this.minX === other.maxX ||
this.maxY === other.minY || this.minY === other.maxY) && (this.maxY >= other.minY && this.minY <= other.maxY &&
this.maxX >= other.minX && this.minX <= other.maxX);
}
;
isCollidingWithOther(other) {
return !(this.maxX <= other.minX ||
this.minX >= other.maxX ||
this.maxY <= other.minY ||
this.minY >= other.maxY);
}
;
setPointCenter(newCenterPoint) {
const newX = newCenterPoint.x - (this.width / 2);
const newY = newCenterPoint.y - (this.height / 2);
this.origin.x = newX;
this.origin.y = newY;
}
;
getCornerPoint(cornerKey) {
switch (cornerKey) {
case 'topLeftPoint':
return this.topLeftPoint.clone();
case 'bottomLeftPoint':
return this.bottomLeftPoint.clone();
case 'bottomRightPoint':
return this.bottomRightPoint.clone();
case 'topRightPoint':
return this.topRightPoint.clone();
}
;
}
;
setCornerPoint(cornerKey, newValue) {
switch (cornerKey) {
case 'topLeftPoint':
this.minX = newValue.x;
this.minY = newValue.y;
break;
case 'bottomLeftPoint':
this.minX = newValue.x;
this.maxY = newValue.y;
break;
case 'bottomRightPoint':
this.maxX = newValue.x;
this.maxY = newValue.y;
break;
case 'topRightPoint':
this.maxX = newValue.x;
this.maxY = newValue.y;
break;
}
;
}
;
applyScaleToNewSize(newSize) {
let center = this.center;
let newX = center.x - (newSize.width / 2);
let newY = center.y - (newSize.height / 2);
this.origin.x = newX;
this.origin.y = newY;
}
;
applyUniformScaleByFactor(args) {
const scaleFactor = args.percentAmount;
let anchor = (() => {
switch (args.anchorReference.mode) {
case 'relativeToOrigin':
return this.origin.clone();
case 'relativeToCenter':
return this.center;
case 'relativeToRectCorner':
return this.getCornerPoint(args.anchorReference.cornerKey);
}
;
})();
const newWidth = this.width * scaleFactor;
const newHeight = this.height * scaleFactor;
this.size = {
width: newWidth,
height: newHeight,
};
switch (args.anchorReference.mode) {
case 'relativeToOrigin':
this.origin = anchor;
break;
case 'relativeToCenter':
this.setPointCenter(anchor);
break;
case 'relativeToRectCorner':
this.setCornerPoint(args.anchorReference.cornerKey, anchor);
break;
}
;
}
scaledUniformallyByFactor(args) {
const clone = this.clone();
clone.applyUniformScaleByFactor(args);
return clone;
}
;
// MARK: - Static Members - Alias Init
// -----------------------------------
static initFromValue(args) {
return new Rect({
mode: 'originAndSize',
...args,
});
}
;
}