pixi.js
Version:
<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">
277 lines (274 loc) • 9.63 kB
JavaScript
import { Rectangle } from './Rectangle.mjs';
"use strict";
const isCornerWithinStroke = (pX, pY, cornerX, cornerY, radius, strokeWidthInner, strokeWidthOuter) => {
const dx = pX - cornerX;
const dy = pY - cornerY;
const distance = Math.sqrt(dx * dx + dy * dy);
return distance >= radius - strokeWidthInner && distance <= radius + strokeWidthOuter;
};
class RoundedRectangle {
/**
* @param x - The X coordinate of the upper-left corner of the rounded rectangle
* @param y - The Y coordinate of the upper-left corner of the rounded rectangle
* @param width - The overall width of this rounded rectangle
* @param height - The overall height of this rounded rectangle
* @param radius - Controls the radius of the rounded corners
*/
constructor(x = 0, y = 0, width = 0, height = 0, radius = 20) {
/**
* The type of the object, mainly used to avoid `instanceof` checks
* @example
* ```ts
* // Check shape type
* const shape = new RoundedRectangle(0, 0, 100, 100, 20);
* console.log(shape.type); // 'roundedRectangle'
*
* // Use in type guards
* if (shape.type === 'roundedRectangle') {
* console.log(shape.radius);
* }
* ```
* @readonly
* @default 'roundedRectangle'
* @see {@link SHAPE_PRIMITIVE} For all shape types
*/
this.type = "roundedRectangle";
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.radius = radius;
}
/**
* Returns the framing rectangle of the rounded rectangle as a Rectangle object
* @example
* ```ts
* // Basic bounds calculation
* const rect = new RoundedRectangle(100, 100, 200, 150, 20);
* const bounds = rect.getBounds();
* // bounds: x=100, y=100, width=200, height=150
*
* // Reuse existing rectangle
* const out = new Rectangle();
* rect.getBounds(out);
* ```
* @remarks
* - Rectangle matches outer dimensions
* - Ignores corner radius
* @param out - Optional rectangle to store the result
* @returns The framing rectangle
* @see {@link Rectangle} For rectangle properties
* @see {@link RoundedRectangle.contains} For checking if a point is inside
*/
getBounds(out) {
out || (out = new Rectangle());
out.x = this.x;
out.y = this.y;
out.width = this.width;
out.height = this.height;
return out;
}
/**
* Creates a clone of this Rounded Rectangle.
* @example
* ```ts
* // Basic cloning
* const original = new RoundedRectangle(100, 100, 200, 150, 20);
* const copy = original.clone();
*
* // Clone and modify
* const modified = original.clone();
* modified.radius = 30;
* modified.width *= 2;
*
* // Verify independence
* console.log(original.radius); // 20
* console.log(modified.radius); // 30
* ```
* @returns A copy of the rounded rectangle
* @see {@link RoundedRectangle.copyFrom} For copying into existing rectangle
* @see {@link RoundedRectangle.copyTo} For copying to another rectangle
*/
clone() {
return new RoundedRectangle(this.x, this.y, this.width, this.height, this.radius);
}
/**
* Copies another rectangle to this one.
* @example
* ```ts
* // Basic copying
* const source = new RoundedRectangle(100, 100, 200, 150, 20);
* const target = new RoundedRectangle();
* target.copyFrom(source);
*
* // Chain with other operations
* const rect = new RoundedRectangle()
* .copyFrom(source)
* .getBounds(rect);
* ```
* @param rectangle - The rectangle to copy from
* @returns Returns itself
* @see {@link RoundedRectangle.copyTo} For copying to another rectangle
* @see {@link RoundedRectangle.clone} For creating new rectangle copy
*/
copyFrom(rectangle) {
this.x = rectangle.x;
this.y = rectangle.y;
this.width = rectangle.width;
this.height = rectangle.height;
return this;
}
/**
* Copies this rectangle to another one.
* @example
* ```ts
* // Basic copying
* const source = new RoundedRectangle(100, 100, 200, 150, 20);
* const target = new RoundedRectangle();
* source.copyTo(target);
*
* // Chain with other operations
* const result = source
* .copyTo(new RoundedRectangle())
* .getBounds();
* ```
* @param rectangle - The rectangle to copy to
* @returns Returns given parameter
* @see {@link RoundedRectangle.copyFrom} For copying from another rectangle
* @see {@link RoundedRectangle.clone} For creating new rectangle copy
*/
copyTo(rectangle) {
rectangle.copyFrom(this);
return rectangle;
}
/**
* Checks whether the x and y coordinates given are contained within this Rounded Rectangle
* @example
* ```ts
* // Basic containment check
* const rect = new RoundedRectangle(100, 100, 200, 150, 20);
* const isInside = rect.contains(150, 125); // true
* // Check corner radius
* const corner = rect.contains(100, 100); // false if within corner curve
* ```
* @remarks
* - Returns false if width/height is 0 or negative
* - Handles rounded corners with radius check
* @param x - The X coordinate of the point to test
* @param y - The Y coordinate of the point to test
* @returns Whether the x/y coordinates are within this Rounded Rectangle
* @see {@link RoundedRectangle.strokeContains} For checking stroke intersection
* @see {@link RoundedRectangle.getBounds} For getting containing rectangle
*/
contains(x, y) {
if (this.width <= 0 || this.height <= 0) {
return false;
}
if (x >= this.x && x <= this.x + this.width) {
if (y >= this.y && y <= this.y + this.height) {
const radius = Math.max(0, Math.min(this.radius, Math.min(this.width, this.height) / 2));
if (y >= this.y + radius && y <= this.y + this.height - radius || x >= this.x + radius && x <= this.x + this.width - radius) {
return true;
}
let dx = x - (this.x + radius);
let dy = y - (this.y + radius);
const radius2 = radius * radius;
if (dx * dx + dy * dy <= radius2) {
return true;
}
dx = x - (this.x + this.width - radius);
if (dx * dx + dy * dy <= radius2) {
return true;
}
dy = y - (this.y + this.height - radius);
if (dx * dx + dy * dy <= radius2) {
return true;
}
dx = x - (this.x + radius);
if (dx * dx + dy * dy <= radius2) {
return true;
}
}
}
return false;
}
/**
* Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
* @example
* ```ts
* // Basic stroke check
* const rect = new RoundedRectangle(100, 100, 200, 150, 20);
* const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width
*
* // Check with different alignments
* const innerStroke = rect.strokeContains(150, 100, 4, 0); // Inside
* const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered
* const outerStroke = rect.strokeContains(150, 100, 4, 1); // Outside
* ```
* @param pX - The X coordinate of the point to test
* @param pY - The Y coordinate of the point to test
* @param strokeWidth - The width of the line to check
* @param alignment - The alignment of the stroke (0 = inner, 0.5 = centered, 1 = outer)
* @returns Whether the x/y coordinates are within this rectangle's stroke
* @see {@link RoundedRectangle.contains} For checking fill containment
* @see {@link RoundedRectangle.getBounds} For getting stroke bounds
*/
strokeContains(pX, pY, strokeWidth, alignment = 0.5) {
const { x, y, width, height, radius } = this;
const strokeWidthOuter = strokeWidth * (1 - alignment);
const strokeWidthInner = strokeWidth - strokeWidthOuter;
const innerX = x + radius;
const innerY = y + radius;
const innerWidth = width - radius * 2;
const innerHeight = height - radius * 2;
const rightBound = x + width;
const bottomBound = y + height;
if ((pX >= x - strokeWidthOuter && pX <= x + strokeWidthInner || pX >= rightBound - strokeWidthInner && pX <= rightBound + strokeWidthOuter) && pY >= innerY && pY <= innerY + innerHeight) {
return true;
}
if ((pY >= y - strokeWidthOuter && pY <= y + strokeWidthInner || pY >= bottomBound - strokeWidthInner && pY <= bottomBound + strokeWidthOuter) && pX >= innerX && pX <= innerX + innerWidth) {
return true;
}
return (
// Top-left
pX < innerX && pY < innerY && isCornerWithinStroke(
pX,
pY,
innerX,
innerY,
radius,
strokeWidthInner,
strokeWidthOuter
) || pX > rightBound - radius && pY < innerY && isCornerWithinStroke(
pX,
pY,
rightBound - radius,
innerY,
radius,
strokeWidthInner,
strokeWidthOuter
) || pX > rightBound - radius && pY > bottomBound - radius && isCornerWithinStroke(
pX,
pY,
rightBound - radius,
bottomBound - radius,
radius,
strokeWidthInner,
strokeWidthOuter
) || pX < innerX && pY > bottomBound - radius && isCornerWithinStroke(
pX,
pY,
innerX,
bottomBound - radius,
radius,
strokeWidthInner,
strokeWidthOuter
)
);
}
toString() {
return `[pixi.js/math:RoundedRectangle x=${this.x} y=${this.y}width=${this.width} height=${this.height} radius=${this.radius}]`;
}
}
export { RoundedRectangle };
//# sourceMappingURL=RoundedRectangle.mjs.map