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">
1 lines • 20 kB
Source Map (JSON)
{"version":3,"file":"RoundedRectangle.mjs","sources":["../../../src/maths/shapes/RoundedRectangle.ts"],"sourcesContent":["import { type SHAPE_PRIMITIVE } from '../misc/const';\nimport { Rectangle } from './Rectangle';\n\nimport type { ShapePrimitive } from './ShapePrimitive';\n\nconst isCornerWithinStroke = (\n pX: number,\n pY: number,\n cornerX: number,\n cornerY: number,\n radius: number,\n strokeWidthInner: number,\n strokeWidthOuter: number\n) =>\n{\n const dx = pX - cornerX;\n const dy = pY - cornerY;\n const distance = Math.sqrt((dx * dx) + (dy * dy));\n\n return distance >= radius - strokeWidthInner && distance <= radius + strokeWidthOuter;\n};\n\n/**\n * The `RoundedRectangle` object represents a rectangle with rounded corners.\n * Defined by position, dimensions and corner radius.\n * @example\n * ```ts\n * // Basic rectangle creation\n * const rect = new RoundedRectangle(100, 100, 200, 150, 20);\n * // Use as container hit area\n * container.hitArea = new RoundedRectangle(0, 0, 100, 100, 10);\n * // Check point containment\n * const isInside = rect.contains(mouseX, mouseY);\n * // Get bounds\n * const bounds = rect.getBounds();\n * ```\n * @remarks\n * - Position defined by top-left corner\n * - Radius clamped to half smallest dimension\n * - Common in UI elements\n * @see {@link Rectangle} For non-rounded rectangles\n * @category maths\n * @standard\n */\nexport class RoundedRectangle implements ShapePrimitive\n{\n /**\n * The X coordinate of the upper-left corner of the rounded rectangle\n * @example\n * ```ts\n * // Basic x position\n * const rect = new RoundedRectangle();\n * rect.x = 100;\n * ```\n * @default 0\n */\n public x: number;\n\n /**\n * The Y coordinate of the upper-left corner of the rounded rectangle\n * @example\n * ```ts\n * // Basic y position\n * const rect = new RoundedRectangle();\n * rect.y = 100;\n * ```\n * @default 0\n */\n public y: number;\n\n /**\n * The overall width of this rounded rectangle\n * @example\n * ```ts\n * // Basic width setting\n * const rect = new RoundedRectangle();\n * rect.width = 200; // Total width will be 200\n * ```\n * @default 0\n */\n public width: number;\n\n /**\n * The overall height of this rounded rectangle\n * @example\n * ```ts\n * // Basic height setting\n * const rect = new RoundedRectangle();\n * rect.height = 150; // Total height will be 150\n * ```\n * @default 0\n */\n public height: number;\n\n /**\n * Controls the radius of the rounded corners\n * @example\n * ```ts\n * // Basic radius setting\n * const rect = new RoundedRectangle(0, 0, 200, 150);\n * rect.radius = 20;\n *\n * // Clamp to maximum safe radius\n * rect.radius = Math.min(rect.width, rect.height) / 2;\n *\n * // Create pill shape\n * rect.radius = rect.height / 2;\n * ```\n * @remarks\n * - Automatically clamped to half of smallest dimension\n * - Common values: 0-20 for UI elements\n * - Higher values create more rounded corners\n * @default 20\n */\n public radius: number;\n\n /**\n * The type of the object, mainly used to avoid `instanceof` checks\n * @example\n * ```ts\n * // Check shape type\n * const shape = new RoundedRectangle(0, 0, 100, 100, 20);\n * console.log(shape.type); // 'roundedRectangle'\n *\n * // Use in type guards\n * if (shape.type === 'roundedRectangle') {\n * console.log(shape.radius);\n * }\n * ```\n * @readonly\n * @default 'roundedRectangle'\n * @see {@link SHAPE_PRIMITIVE} For all shape types\n */\n public readonly type: SHAPE_PRIMITIVE = 'roundedRectangle';\n\n /**\n * @param x - The X coordinate of the upper-left corner of the rounded rectangle\n * @param y - The Y coordinate of the upper-left corner of the rounded rectangle\n * @param width - The overall width of this rounded rectangle\n * @param height - The overall height of this rounded rectangle\n * @param radius - Controls the radius of the rounded corners\n */\n constructor(x = 0, y = 0, width = 0, height = 0, radius = 20)\n {\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.radius = radius;\n }\n\n /**\n * Returns the framing rectangle of the rounded rectangle as a Rectangle object\n * @example\n * ```ts\n * // Basic bounds calculation\n * const rect = new RoundedRectangle(100, 100, 200, 150, 20);\n * const bounds = rect.getBounds();\n * // bounds: x=100, y=100, width=200, height=150\n *\n * // Reuse existing rectangle\n * const out = new Rectangle();\n * rect.getBounds(out);\n * ```\n * @remarks\n * - Rectangle matches outer dimensions\n * - Ignores corner radius\n * @param out - Optional rectangle to store the result\n * @returns The framing rectangle\n * @see {@link Rectangle} For rectangle properties\n * @see {@link RoundedRectangle.contains} For checking if a point is inside\n */\n public getBounds(out?: Rectangle): Rectangle\n {\n out ||= new Rectangle();\n\n out.x = this.x;\n out.y = this.y;\n out.width = this.width;\n out.height = this.height;\n\n return out;\n }\n\n /**\n * Creates a clone of this Rounded Rectangle.\n * @example\n * ```ts\n * // Basic cloning\n * const original = new RoundedRectangle(100, 100, 200, 150, 20);\n * const copy = original.clone();\n *\n * // Clone and modify\n * const modified = original.clone();\n * modified.radius = 30;\n * modified.width *= 2;\n *\n * // Verify independence\n * console.log(original.radius); // 20\n * console.log(modified.radius); // 30\n * ```\n * @returns A copy of the rounded rectangle\n * @see {@link RoundedRectangle.copyFrom} For copying into existing rectangle\n * @see {@link RoundedRectangle.copyTo} For copying to another rectangle\n */\n public clone(): RoundedRectangle\n {\n return new RoundedRectangle(this.x, this.y, this.width, this.height, this.radius);\n }\n\n /**\n * Copies another rectangle to this one.\n * @example\n * ```ts\n * // Basic copying\n * const source = new RoundedRectangle(100, 100, 200, 150, 20);\n * const target = new RoundedRectangle();\n * target.copyFrom(source);\n *\n * // Chain with other operations\n * const rect = new RoundedRectangle()\n * .copyFrom(source)\n * .getBounds(rect);\n * ```\n * @param rectangle - The rectangle to copy from\n * @returns Returns itself\n * @see {@link RoundedRectangle.copyTo} For copying to another rectangle\n * @see {@link RoundedRectangle.clone} For creating new rectangle copy\n */\n public copyFrom(rectangle: RoundedRectangle): this\n {\n this.x = rectangle.x;\n this.y = rectangle.y;\n this.width = rectangle.width;\n this.height = rectangle.height;\n\n return this;\n }\n\n /**\n * Copies this rectangle to another one.\n * @example\n * ```ts\n * // Basic copying\n * const source = new RoundedRectangle(100, 100, 200, 150, 20);\n * const target = new RoundedRectangle();\n * source.copyTo(target);\n *\n * // Chain with other operations\n * const result = source\n * .copyTo(new RoundedRectangle())\n * .getBounds();\n * ```\n * @param rectangle - The rectangle to copy to\n * @returns Returns given parameter\n * @see {@link RoundedRectangle.copyFrom} For copying from another rectangle\n * @see {@link RoundedRectangle.clone} For creating new rectangle copy\n */\n public copyTo(rectangle: RoundedRectangle): RoundedRectangle\n {\n rectangle.copyFrom(this);\n\n return rectangle;\n }\n\n /**\n * Checks whether the x and y coordinates given are contained within this Rounded Rectangle\n * @example\n * ```ts\n * // Basic containment check\n * const rect = new RoundedRectangle(100, 100, 200, 150, 20);\n * const isInside = rect.contains(150, 125); // true\n * // Check corner radius\n * const corner = rect.contains(100, 100); // false if within corner curve\n * ```\n * @remarks\n * - Returns false if width/height is 0 or negative\n * - Handles rounded corners with radius check\n * @param x - The X coordinate of the point to test\n * @param y - The Y coordinate of the point to test\n * @returns Whether the x/y coordinates are within this Rounded Rectangle\n * @see {@link RoundedRectangle.strokeContains} For checking stroke intersection\n * @see {@link RoundedRectangle.getBounds} For getting containing rectangle\n */\n public contains(x: number, y: number): boolean\n {\n if (this.width <= 0 || this.height <= 0)\n {\n return false;\n }\n if (x >= this.x && x <= this.x + this.width)\n {\n if (y >= this.y && y <= this.y + this.height)\n {\n const radius = Math.max(0, Math.min(this.radius, Math.min(this.width, this.height) / 2));\n\n if ((y >= this.y + radius && y <= this.y + this.height - radius)\n || (x >= this.x + radius && x <= this.x + this.width - radius))\n {\n return true;\n }\n let dx = x - (this.x + radius);\n let dy = y - (this.y + radius);\n const radius2 = radius * radius;\n\n if ((dx * dx) + (dy * dy) <= radius2)\n {\n return true;\n }\n dx = x - (this.x + this.width - radius);\n if ((dx * dx) + (dy * dy) <= radius2)\n {\n return true;\n }\n dy = y - (this.y + this.height - radius);\n if ((dx * dx) + (dy * dy) <= radius2)\n {\n return true;\n }\n dx = x - (this.x + radius);\n if ((dx * dx) + (dy * dy) <= radius2)\n {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Checks whether the x and y coordinates given are contained within this rectangle including the stroke.\n * @example\n * ```ts\n * // Basic stroke check\n * const rect = new RoundedRectangle(100, 100, 200, 150, 20);\n * const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width\n *\n * // Check with different alignments\n * const innerStroke = rect.strokeContains(150, 100, 4, 0); // Inside\n * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered\n * const outerStroke = rect.strokeContains(150, 100, 4, 1); // Outside\n * ```\n * @param pX - The X coordinate of the point to test\n * @param pY - The Y coordinate of the point to test\n * @param strokeWidth - The width of the line to check\n * @param alignment - The alignment of the stroke (0 = inner, 0.5 = centered, 1 = outer)\n * @returns Whether the x/y coordinates are within this rectangle's stroke\n * @see {@link RoundedRectangle.contains} For checking fill containment\n * @see {@link RoundedRectangle.getBounds} For getting stroke bounds\n */\n public strokeContains(pX: number, pY: number, strokeWidth: number, alignment: number = 0.5): boolean\n {\n const { x, y, width, height, radius } = this;\n\n const strokeWidthOuter = strokeWidth * (1 - alignment);\n const strokeWidthInner = strokeWidth - strokeWidthOuter;\n\n const innerX = x + radius;\n const innerY = y + radius;\n const innerWidth = width - (radius * 2);\n const innerHeight = height - (radius * 2);\n const rightBound = x + width;\n const bottomBound = y + height;\n\n // Check if point is within the vertical edges (excluding corners)\n if (((pX >= x - strokeWidthOuter && pX <= x + strokeWidthInner)\n || (pX >= rightBound - strokeWidthInner && pX <= rightBound + strokeWidthOuter))\n && pY >= innerY && pY <= innerY + innerHeight)\n {\n return true;\n }\n\n // Check if point is within the horizontal edges (excluding corners)\n if (((pY >= y - strokeWidthOuter && pY <= y + strokeWidthInner)\n || (pY >= bottomBound - strokeWidthInner && pY <= bottomBound + strokeWidthOuter))\n && pX >= innerX && pX <= innerX + innerWidth)\n {\n return true;\n }\n\n // Top-left, top-right, bottom-right, bottom-left corners\n return (\n // Top-left\n (pX < innerX && pY < innerY\n && isCornerWithinStroke(pX, pY, innerX, innerY,\n radius, strokeWidthInner, strokeWidthOuter))\n // top-right\n || (pX > rightBound - radius && pY < innerY\n && isCornerWithinStroke(pX, pY, rightBound - radius, innerY,\n radius, strokeWidthInner, strokeWidthOuter))\n // bottom-right\n || (pX > rightBound - radius && pY > bottomBound - radius\n && isCornerWithinStroke(pX, pY, rightBound - radius, bottomBound - radius,\n radius, strokeWidthInner, strokeWidthOuter))\n // bottom-left\n || (pX < innerX && pY > bottomBound - radius\n && isCornerWithinStroke(pX, pY, innerX, bottomBound - radius,\n radius, strokeWidthInner, strokeWidthOuter)));\n }\n\n // #if _DEBUG\n public toString(): string\n {\n return `[pixi.js/math:RoundedRectangle x=${this.x} y=${this.y}`\n + `width=${this.width} height=${this.height} radius=${this.radius}]`;\n }\n // #endif\n}\n"],"names":[],"mappings":"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"}