UNPKG

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">

824 lines (820 loc) 25.5 kB
'use strict'; var deprecation = require('../../../utils/logging/deprecation.js'); var ViewContainer = require('../../view/ViewContainer.js'); var GraphicsContext = require('./GraphicsContext.js'); "use strict"; class Graphics extends ViewContainer.ViewContainer { /** * Creates a new Graphics object. * @param options - Options for the Graphics. */ constructor(options) { if (options instanceof GraphicsContext.GraphicsContext) { options = { context: options }; } const { context, roundPixels, ...rest } = options || {}; super({ label: "Graphics", ...rest }); /** @internal */ this.renderPipeId = "graphics"; if (!context) { this._context = this._ownedContext = new GraphicsContext.GraphicsContext(); } else { this._context = context; } this._context.on("update", this.onViewUpdate, this); this.didViewUpdate = true; this.allowChildren = false; this.roundPixels = roundPixels ?? false; } set context(context) { if (context === this._context) return; this._context.off("update", this.onViewUpdate, this); this._context = context; this._context.on("update", this.onViewUpdate, this); this.onViewUpdate(); } /** * The underlying graphics context used for drawing operations. * Controls how shapes and paths are rendered. * @example * ```ts * // Create a shared context * const sharedContext = new GraphicsContext(); * * // Create graphics objects sharing the same context * const graphics1 = new Graphics(); * const graphics2 = new Graphics(); * * // Assign shared context * graphics1.context = sharedContext; * graphics2.context = sharedContext; * * // Both graphics will show the same shapes * sharedContext * .rect(0, 0, 100, 100) * .fill({ color: 0xff0000 }); * ``` * @see {@link GraphicsContext} For drawing operations * @see {@link GraphicsOptions} For context configuration */ get context() { return this._context; } /** * The local bounds of the graphics object. * Returns the boundaries after all graphical operations but before any transforms. * @example * ```ts * const graphics = new Graphics(); * * // Draw a shape * graphics * .rect(0, 0, 100, 100) * .fill({ color: 0xff0000 }); * * // Get bounds information * const bounds = graphics.bounds; * console.log(bounds.width); // 100 * console.log(bounds.height); // 100 * ``` * @readonly * @see {@link Bounds} For bounds operations * @see {@link Container#getBounds} For transformed bounds */ get bounds() { return this._context.bounds; } /** * Graphics objects do not need to update their bounds as the context handles this. * @private */ updateBounds() { } /** * Checks if the object contains the given point. * Returns true if the point lies within the Graphics object's rendered area. * @example * ```ts * const graphics = new Graphics(); * * // Draw a shape * graphics * .rect(0, 0, 100, 100) * .fill({ color: 0xff0000 }); * * // Check point intersection * if (graphics.containsPoint({ x: 50, y: 50 })) { * console.log('Point is inside rectangle!'); * } * ``` * @param point - The point to check in local coordinates * @returns True if the point is inside the Graphics object * @see {@link Graphics#bounds} For bounding box checks * @see {@link PointData} For point data structure */ containsPoint(point) { return this._context.containsPoint(point); } /** * Destroys this graphics renderable and optionally its context. * @param options - Options parameter. A boolean will act as if all options * * If the context was created by this graphics and `destroy(false)` or `destroy()` is called * then the context will still be destroyed. * * If you want to explicitly not destroy this context that this graphics created, * then you should pass destroy({ context: false }) * * If the context was passed in as an argument to the constructor then it will not be destroyed * @example * ```ts * // Destroy the graphics and its context * graphics.destroy(); * graphics.destroy(true); * graphics.destroy({ context: true, texture: true, textureSource: true }); * ``` */ destroy(options) { if (this._ownedContext && !options) { this._ownedContext.destroy(options); } else if (options === true || options?.context === true) { this._context.destroy(options); } this._ownedContext = null; this._context = null; super.destroy(options); } _callContextMethod(method, args) { this.context[method](...args); return this; } // --------------------------------------- GraphicsContext methods --------------------------------------- /** * Sets the current fill style of the graphics context. * The fill style can be a color, gradient, pattern, or a complex style object. * @example * ```ts * const graphics = new Graphics(); * * // Basic color fill * graphics * .setFillStyle({ color: 0xff0000 }) // Red fill * .rect(0, 0, 100, 100) * .fill(); * * // Gradient fill * const gradient = new FillGradient({ * end: { x: 1, y: 0 }, * colorStops: [ * { offset: 0, color: 0xff0000 }, // Red at start * { offset: 0.5, color: 0x00ff00 }, // Green at middle * { offset: 1, color: 0x0000ff }, // Blue at end * ], * }); * * graphics * .setFillStyle(gradient) * .circle(100, 100, 50) * .fill(); * * // Pattern fill * const pattern = new FillPattern(texture); * graphics * .setFillStyle({ * fill: pattern, * alpha: 0.5 * }) * .rect(0, 0, 200, 200) * .fill(); * ``` * @param {FillInput} args - The fill style to apply * @returns The Graphics instance for chaining * @see {@link FillStyle} For fill style options * @see {@link FillGradient} For gradient fills * @see {@link FillPattern} For pattern fills */ setFillStyle(...args) { return this._callContextMethod("setFillStyle", args); } /** * Sets the current stroke style of the graphics context. * Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations. * @example * ```ts * const graphics = new Graphics(); * * // Basic color stroke * graphics * .setStrokeStyle({ * width: 2, * color: 0x000000 * }) * .rect(0, 0, 100, 100) * .stroke(); * * // Complex stroke style * graphics * .setStrokeStyle({ * width: 4, * color: 0xff0000, * alpha: 0.5, * join: 'round', * cap: 'round', * alignment: 0.5 * }) * .circle(100, 100, 50) * .stroke(); * * // Gradient stroke * const gradient = new FillGradient({ * end: { x: 1, y: 0 }, * colorStops: [ * { offset: 0, color: 0xff0000 }, // Red at start * { offset: 0.5, color: 0x00ff00 }, // Green at middle * { offset: 1, color: 0x0000ff }, // Blue at end * ], * }); * * graphics * .setStrokeStyle({ * width: 10, * fill: gradient * }) * .poly([0,0, 100,50, 0,100]) * .stroke(); * ``` * @param {StrokeInput} args - The stroke style to apply * @returns The Graphics instance for chaining * @see {@link StrokeStyle} For stroke style options * @see {@link FillGradient} For gradient strokes * @see {@link FillPattern} For pattern strokes */ setStrokeStyle(...args) { return this._callContextMethod("setStrokeStyle", args); } fill(...args) { return this._callContextMethod("fill", args); } /** * Strokes the current path with the current stroke style or specified style. * Outlines the shape using the stroke settings. * @example * ```ts * const graphics = new Graphics(); * * // Stroke with direct color * graphics * .circle(50, 50, 25) * .stroke({ * width: 2, * color: 0xff0000 * }); // 2px red stroke * * // Fill with texture * graphics * .rect(0, 0, 100, 100) * .stroke(myTexture); // Fill with texture * * // Stroke with gradient * const gradient = new FillGradient({ * end: { x: 1, y: 0 }, * colorStops: [ * { offset: 0, color: 0xff0000 }, * { offset: 0.5, color: 0x00ff00 }, * { offset: 1, color: 0x0000ff }, * ], * }); * * graphics * .rect(0, 0, 100, 100) * .stroke({ * width: 4, * fill: gradient, * alignment: 0.5, * join: 'round' * }); * ``` * @param {StrokeStyle} args - Optional stroke style to apply. Can be: * - A stroke style object with width, color, etc. * - A gradient * - A pattern * If omitted, uses current stroke style. * @returns The Graphics instance for chaining * @see {@link StrokeStyle} For stroke style options * @see {@link FillGradient} For gradient strokes * @see {@link setStrokeStyle} For setting default stroke style */ stroke(...args) { return this._callContextMethod("stroke", args); } texture(...args) { return this._callContextMethod("texture", args); } /** * Resets the current path. Any previous path and its commands are discarded and a new path is * started. This is typically called before beginning a new shape or series of drawing commands. * @example * ```ts * const graphics = new Graphics(); * graphics * .circle(150, 150, 50) * .fill({ color: 0x00ff00 }) * .beginPath() // Starts a new path * .circle(250, 150, 50) * .fill({ color: 0x0000ff }); * ``` * @returns The Graphics instance for chaining * @see {@link Graphics#moveTo} For starting a new subpath * @see {@link Graphics#closePath} For closing the current path */ beginPath() { return this._callContextMethod("beginPath", []); } /** * Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by * subtracting a path from the previously drawn path. * * If a hole is not completely in a shape, it will fail to cut correctly. * @example * ```ts * const graphics = new Graphics(); * * // Draw outer circle * graphics * .circle(100, 100, 50) * .fill({ color: 0xff0000 }); * .circle(100, 100, 25) // Inner circle * .cut() // Cuts out the inner circle from the outer circle * ``` */ cut() { return this._callContextMethod("cut", []); } arc(...args) { return this._callContextMethod("arc", args); } arcTo(...args) { return this._callContextMethod("arcTo", args); } arcToSvg(...args) { return this._callContextMethod("arcToSvg", args); } bezierCurveTo(...args) { return this._callContextMethod("bezierCurveTo", args); } /** * Closes the current path by drawing a straight line back to the start point. * * This is useful for completing shapes and ensuring they are properly closed for fills. * @example * ```ts * // Create a triangle with closed path * const graphics = new Graphics(); * graphics * .moveTo(50, 50) * .lineTo(100, 100) * .lineTo(0, 100) * .closePath() * ``` * @returns The Graphics instance for method chaining * @see {@link Graphics#beginPath} For starting a new path * @see {@link Graphics#fill} For filling closed paths * @see {@link Graphics#stroke} For stroking paths */ closePath() { return this._callContextMethod("closePath", []); } ellipse(...args) { return this._callContextMethod("ellipse", args); } circle(...args) { return this._callContextMethod("circle", args); } path(...args) { return this._callContextMethod("path", args); } lineTo(...args) { return this._callContextMethod("lineTo", args); } moveTo(...args) { return this._callContextMethod("moveTo", args); } quadraticCurveTo(...args) { return this._callContextMethod("quadraticCurveTo", args); } rect(...args) { return this._callContextMethod("rect", args); } roundRect(...args) { return this._callContextMethod("roundRect", args); } poly(...args) { return this._callContextMethod("poly", args); } regularPoly(...args) { return this._callContextMethod("regularPoly", args); } roundPoly(...args) { return this._callContextMethod("roundPoly", args); } roundShape(...args) { return this._callContextMethod("roundShape", args); } filletRect(...args) { return this._callContextMethod("filletRect", args); } chamferRect(...args) { return this._callContextMethod("chamferRect", args); } star(...args) { return this._callContextMethod("star", args); } svg(...args) { return this._callContextMethod("svg", args); } restore(...args) { return this._callContextMethod("restore", args); } /** * Saves the current graphics state onto a stack. The state includes: * - Current transformation matrix * - Current fill style * - Current stroke style * @example * ```ts * const graphics = new Graphics(); * * // Save state before complex operations * graphics.save(); * * // Create transformed and styled shape * graphics * .translateTransform(100, 100) * .rotateTransform(Math.PI / 4) * .setFillStyle({ * color: 0xff0000, * alpha: 0.5 * }) * .rect(-25, -25, 50, 50) * .fill(); * * // Restore to original state * graphics.restore(); * * // Continue drawing with previous state * graphics * .circle(50, 50, 25) * .fill(); * ``` * @returns The Graphics instance for method chaining * @see {@link Graphics#restore} For restoring the saved state * @see {@link Graphics#setTransform} For setting transformations */ save() { return this._callContextMethod("save", []); } /** * Returns the current transformation matrix of the graphics context. * This matrix represents all accumulated transformations including translate, scale, and rotate. * @example * ```ts * const graphics = new Graphics(); * * // Apply some transformations * graphics * .translateTransform(100, 100) * .rotateTransform(Math.PI / 4); * * // Get the current transform matrix * const matrix = graphics.getTransform(); * console.log(matrix.tx, matrix.ty); // 100, 100 * * // Use the matrix for other operations * graphics * .setTransform(matrix) * .circle(0, 0, 50) * .fill({ color: 0xff0000 }); * ``` * @returns The current transformation matrix. * @see {@link Graphics#setTransform} For setting the transform matrix * @see {@link Matrix} For matrix operations */ getTransform() { return this.context.getTransform(); } /** * Resets the current transformation matrix to the identity matrix, effectively removing * any transformations (rotation, scaling, translation) previously applied. * @example * ```ts * const graphics = new Graphics(); * * // Apply transformations * graphics * .translateTransform(100, 100) * .scaleTransform(2, 2) * .circle(0, 0, 25) * .fill({ color: 0xff0000 }); * // Reset transform to default state * graphics * .resetTransform() * .circle(50, 50, 25) // Will draw at actual coordinates * .fill({ color: 0x00ff00 }); * ``` * @returns The Graphics instance for method chaining * @see {@link Graphics#getTransform} For getting the current transform * @see {@link Graphics#setTransform} For setting a specific transform * @see {@link Graphics#save} For saving the current transform state * @see {@link Graphics#restore} For restoring a previous transform state */ resetTransform() { return this._callContextMethod("resetTransform", []); } rotateTransform(...args) { return this._callContextMethod("rotate", args); } scaleTransform(...args) { return this._callContextMethod("scale", args); } setTransform(...args) { return this._callContextMethod("setTransform", args); } transform(...args) { return this._callContextMethod("transform", args); } translateTransform(...args) { return this._callContextMethod("translate", args); } /** * Clears all drawing commands from the graphics context, effectively resetting it. * This includes clearing the current path, fill style, stroke style, and transformations. * * > [!NOTE] Graphics objects are not designed to be continuously cleared and redrawn. * > Instead, they are intended to be used for static or semi-static graphics that * > can be redrawn as needed. Frequent clearing and redrawing may lead to performance issues. * @example * ```ts * const graphics = new Graphics(); * * // Draw some shapes * graphics * .circle(100, 100, 50) * .fill({ color: 0xff0000 }) * .rect(200, 100, 100, 50) * .fill({ color: 0x00ff00 }); * * // Clear all graphics * graphics.clear(); * * // Start fresh with new shapes * graphics * .circle(150, 150, 30) * .fill({ color: 0x0000ff }); * ``` * @returns The Graphics instance for method chaining * @see {@link Graphics#beginPath} For starting a new path without clearing styles * @see {@link Graphics#save} For saving the current state * @see {@link Graphics#restore} For restoring a previous state */ clear() { return this._callContextMethod("clear", []); } /** * Gets or sets the current fill style for the graphics context. The fill style determines * how shapes are filled when using the fill() method. * @example * ```ts * const graphics = new Graphics(); * * // Basic color fill * graphics.fillStyle = { * color: 0xff0000, // Red * alpha: 1 * }; * * // Using gradients * const gradient = new FillGradient({ * end: { x: 0, y: 1 }, // Vertical gradient * stops: [ * { offset: 0, color: 0xff0000, alpha: 1 }, // Start color * { offset: 1, color: 0x0000ff, alpha: 1 } // End color * ] * }); * * graphics.fillStyle = { * fill: gradient, * alpha: 0.8 * }; * * // Using patterns * graphics.fillStyle = { * texture: myTexture, * alpha: 1, * matrix: new Matrix() * .scale(0.5, 0.5) * .rotate(Math.PI / 4) * }; * ``` * @type {ConvertedFillStyle} * @see {@link FillStyle} For all available fill style options * @see {@link FillGradient} For creating gradient fills * @see {@link Graphics#fill} For applying the fill to paths */ get fillStyle() { return this._context.fillStyle; } set fillStyle(value) { this._context.fillStyle = value; } /** * Gets or sets the current stroke style for the graphics context. The stroke style determines * how paths are outlined when using the stroke() method. * @example * ```ts * const graphics = new Graphics(); * * // Basic stroke style * graphics.strokeStyle = { * width: 2, * color: 0xff0000, * alpha: 1 * }; * * // Using with gradients * const gradient = new FillGradient({ * end: { x: 0, y: 1 }, * stops: [ * { offset: 0, color: 0xff0000, alpha: 1 }, * { offset: 1, color: 0x0000ff, alpha: 1 } * ] * }); * * graphics.strokeStyle = { * width: 4, * fill: gradient, * alignment: 0.5, * join: 'round', * cap: 'round' * }; * * // Complex stroke settings * graphics.strokeStyle = { * width: 6, * color: 0x00ff00, * alpha: 0.5, * join: 'miter', * miterLimit: 10, * }; * ``` * @see {@link StrokeStyle} For all available stroke style options * @see {@link Graphics#stroke} For applying the stroke to paths */ get strokeStyle() { return this._context.strokeStyle; } set strokeStyle(value) { this._context.strokeStyle = value; } /** * Creates a new Graphics object that copies the current graphics content. * The clone can either share the same context (shallow clone) or have its own independent * context (deep clone). * @example * ```ts * const graphics = new Graphics(); * * // Create original graphics content * graphics * .circle(100, 100, 50) * .fill({ color: 0xff0000 }); * * // Create a shallow clone (shared context) * const shallowClone = graphics.clone(); * * // Changes to original affect the clone * graphics * .circle(200, 100, 30) * .fill({ color: 0x00ff00 }); * * // Create a deep clone (independent context) * const deepClone = graphics.clone(true); * * // Modify deep clone independently * deepClone * .translateTransform(100, 100) * .circle(0, 0, 40) * .fill({ color: 0x0000ff }); * ``` * @param deep - Whether to create a deep clone of the graphics object. * If false (default), the context will be shared between objects. * If true, creates an independent copy of the context. * @returns A new Graphics instance with either shared or copied context * @see {@link Graphics#context} For accessing the underlying graphics context * @see {@link GraphicsContext} For understanding the shared context behavior */ clone(deep = false) { if (deep) { return new Graphics(this._context.clone()); } this._ownedContext = null; const clone = new Graphics(this._context); return clone; } // -------- v7 deprecations --------- /** * @param width * @param color * @param alpha * @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead */ lineStyle(width, color, alpha) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style."); const strokeStyle = {}; width && (strokeStyle.width = width); color && (strokeStyle.color = color); alpha && (strokeStyle.alpha = alpha); this.context.strokeStyle = strokeStyle; return this; } /** * @param color * @param alpha * @deprecated since 8.0.0 Use {@link Graphics#fill} instead */ beginFill(color, alpha) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."); const fillStyle = {}; if (color !== void 0) fillStyle.color = color; if (alpha !== void 0) fillStyle.alpha = alpha; this.context.fillStyle = fillStyle; return this; } /** * @deprecated since 8.0.0 Use {@link Graphics#fill} instead */ endFill() { deprecation.deprecation(deprecation.v8_0_0, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style."); this.context.fill(); const strokeStyle = this.context.strokeStyle; if (strokeStyle.width !== GraphicsContext.GraphicsContext.defaultStrokeStyle.width || strokeStyle.color !== GraphicsContext.GraphicsContext.defaultStrokeStyle.color || strokeStyle.alpha !== GraphicsContext.GraphicsContext.defaultStrokeStyle.alpha) { this.context.stroke(); } return this; } /** * @param {...any} args * @deprecated since 8.0.0 Use {@link Graphics#circle} instead */ drawCircle(...args) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawCircle has been renamed to Graphics#circle"); return this._callContextMethod("circle", args); } /** * @param {...any} args * @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead */ drawEllipse(...args) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawEllipse has been renamed to Graphics#ellipse"); return this._callContextMethod("ellipse", args); } /** * @param {...any} args * @deprecated since 8.0.0 Use {@link Graphics#poly} instead */ drawPolygon(...args) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawPolygon has been renamed to Graphics#poly"); return this._callContextMethod("poly", args); } /** * @param {...any} args * @deprecated since 8.0.0 Use {@link Graphics#rect} instead */ drawRect(...args) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawRect has been renamed to Graphics#rect"); return this._callContextMethod("rect", args); } /** * @param {...any} args * @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead */ drawRoundedRect(...args) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect"); return this._callContextMethod("roundRect", args); } /** * @param {...any} args * @deprecated since 8.0.0 Use {@link Graphics#star} instead */ drawStar(...args) { deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawStar has been renamed to Graphics#star"); return this._callContextMethod("star", args); } } exports.Graphics = Graphics; //# sourceMappingURL=Graphics.js.map