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
JavaScript
'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