关于 pixijs-scene-graphics
面向 PixiJS v8 开发者的 Graphics 技能,介绍在场景图中绘制矢量形状、路径并应用样式。还涵盖渐变、纹理、裁切、SVG 和共享绘图上下文。
主要功能
- 01绘制形状与复杂路径
- 02应用填充、描边、渐变和图案
- 03通过 cut() 创建镂空
- 04导入和导出 SVG
- 05共享 GraphicsContext
适用场景
- 01绘制界面图形和矢量元素
- 02制作带渐变或纹理的形状
- 03将 Graphics 用作遮罩
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pixijs/ pixijs-skills --skill pixijs-scene-graphics安装后在 Claude Code 中输入/pixijs-scene-graphics确认已加载。
详细介绍
Graphics 是 PixiJS v8 场景图中的矢量绘图叶节点。v8 API 采用先形状、后样式的模式:先使用 rect、circle、moveTo 等方法绘制形状或路径,再应用 fill 和/或 stroke。每个方法都会返回 this 以便链式调用,绘图指令则存储在可由多个实例共享的 GraphicsContext 中。
假设你熟悉 pixijs-scene-core-concepts。Graphics 是叶节点:不要在其中嵌套子节点。将多个 Graphics 对象放在 Container 中进行分组。
快速入门
const g = new Graphics();
g.rect(10, 10, 200, 100)
.fill({ color: 0x3498db, alpha: 0.8 })
.stroke({ width: 3, color: 0x2c3e50 });
g.circle(300, 60, 40).fill(0xe74c3c);
g.moveTo(50, 200)
.lineTo(200, 200)
.bezierCurveTo(250, 250, 100, 300, 50, 250)
.closePath()
.fill(0x6c5ce7);
app.stage.addChild(g);
相关技能: pixijs-scene-core-concepts(场景图基础)、pixijs-scene-container(将图形与其他对象分组)、pixijs-scene-core-concepts/references/masking.md(将 Graphics 用作模板遮罩)、pixijs-filters(特效)、pixijs-performance(批处理、cacheAsTexture)。
构造函数选项
所有 Container 选项(position、scale、tint、label、filters、zIndex 等)在这里同样有效——请参阅 skills/pixijs-scene-core-concepts/references/constructor-options.md。
由 GraphicsOptions 添加的叶节点专属选项:
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
context | GraphicsContext | new GraphicsContext() | 共享绘图上下文。传入上下文可在多个 Graphics 节点间复用其镶嵌几何数据,避免重复的 GPU 运算。如果省略,每个 Graphics 都会创建并持有一个新上下文。 |
roundPixels | boolean | false | 将最终屏幕上的 x/y 舍入到最接近的像素。这样能让像素艺术风格的线条更清晰,但会牺牲平滑的亚像素移动效果。 |
构造函数也接受 GraphicsContext 实例作为唯一参数(new Graphics(ctx)),这是 new Graphics({ context: ctx }) 的简写形式。
核心模式
先定义形状再填充的工作流
const g = new Graphics();
g.rect(10, 10, 200, 100)
.fill({ color: 0x3498db, alpha: 0.8 })
.stroke({ width: 3, color: 0x2c3e50 });
g.circle(150, 200, 40).fill(0xe74c3c);
g.roundRect(300, 10, 150, 80, 12).fill(0x2ecc71);
g.poly([0, 0, 60, 0, 30, 50], true).fill(0x9b59b6);
g.star(400, 200, 5, 40, 20, 0).fill(0xf39c12);
g.ellipse(100, 350, 60, 30).fill(0x1abc9c);
fill() 接受 FillInput:颜色数字或字符串、{ color, alpha, texture, matrix, textureSpace }、FillGradient、FillPattern 或 Texture。使用纹理填充时,textureSpace 控制坐标映射:
'local'(默认):缩放纹理以适应每个形状的边界框(归一化的 0-1 坐标)。'global':纹理的位置和缩放相对于 Graphics 对象的坐标系,所有形状共享。- 图集子纹理:
'global'会遵循帧的原点和旋转,因此以帧的尺寸绘制的形状会与该帧的Sprite匹配。'local'会映射整个源图像;传入一个将目标设为源图像中帧区域的matrix,或者先对帧使用renderer.generateTexture()。
FillInput 还支持嵌套的 fill 子字段:FillStyle 选项对象可以在其 fill 键下嵌入 FillGradient 或 FillPattern,从而将渐变或图案与外层对象的 color、alpha、texture 和 matrix 修饰项一并应用。
stroke() 接受颜色、FillGradient、FillPattern,或一个将所有 FillStyle 键(color、alpha、texture、matrix、fill、textureSpace)与描边属性组合在一起的 StrokeStyle 对象:
| 属性 | 默认值 | 说明 |
|---|---|---|
width | 1 | 描边的像素宽度。 |
cap | 'butt' | 可选值为 'butt'、'round'、'square'。开放路径的端点样式。 |
join | 'miter' | 可选值为 'miter'、'round'、'bevel'。拐角样式。 |
miterLimit | 10 | 限制斜接连接的延伸距离,超过后会改用斜角连接。 |
alignment | 0.5 | 1 = 形状内部,0.5 = 居中,0 = 形状外部。 |
pixelLine | false | 将 1 像素线条对齐到像素网格,以获得清晰的输出。仅适用于 Graphics。 |
描边可以像填充一样使用渐变和图案,例如 fill: gradient 或 texture: tex:
const grad = new FillGradient({
end: { x: 1, y: 0 },
colorStops: [
{ offset: 0, color: 0xff0000 },
{ offset: 1, color: 0x0000ff },
],
});
g.rect(0, 0, 200, 100).stroke({
width: 8,
fill: grad,
join: "round",
cap: "round",
});
对同一形状调用 fill() 和 stroke() 时,可以先后调用;在 fill() 后立即调用 stroke() 会复用同一路径。
高级形状图元
g.regularPoly(100, 100, 50, 6, 0).fill(0x3498db);
g.roundPoly(250, 100, 50, 5, 10).fill(0xe74c3c);
g.chamferRect(350, 50, 100, 80, 15).fill(0x2ecc71);
g.filletRect(500, 50, 100, 80, 15).fill(0x9b59b6);
g.roundShape(
[
{ x: 50, y: 250, radius: 20 },
{ x: 150, y: 250, radius: 5 },
{ x: 150, y: 350, radius: 10 },
{ x: 50, y: 350, radius: 15 },
],
10,
).fill(0xf39c12);
使用 cut() 创建镂空
g.rect(0, 0, 200, 200).fill(0x00ff00).circle(100, 100, 50).cut();
cut() 会从之前绘制的填充或描边中减去当前活动路径。规则如下:
- 镂空必须完全位于目标形状内部。由于渲染器会将镂空作为内部边界进行三角剖分,与边缘重叠或位于形状外部的镂空无法正确渲染。
cut()会回溯最多最近两条指令。使用fill()后再对同一路径调用stroke()时,第一次cut()会先将镂空添加到描边;第二次cut()则会将镂空添加到下方的填充。- 调用
cut()后,活动路径会重置,因此可以使用moveTo、rect等方法开始下一个形状。 cut()也适用于描边——g.rect(...).stroke(...).circle(...).cut()会在描边轮廓上切出一个孔。
调用 cut() 前,在活动路径中绘制多个形状,即可一次镂空多个位置。每个形状都会累加到同一个镂空路径中:
const g = new Graphics();
g.rect(350, 350, 150, 150).fill(0x00ff00);
// Draw three circles into the active path, then cut them all in one call
g.circle(375, 375, 25);
g.circle(425, 425, 25);
g.circle(475, 475, 25);
g.cut();
如果需要在彼此独立的填充形状上镂空,请为每个形状分别调用 fill() 和对应的 cut():
g.rect(0, 0, 100, 100).fill(0x3498db);
g.circle(50, 50, 20).cut(); // hole in the rect
g.rect(120, 0, 100, 100).fill(0xe74c3c);
g.circle(170, 50, 20).cut(); // hole in the second rect
对已有镂空的形状调用 cut() 时,会添加到现有镂空路径中,而不是替换它。可以用这种方式叠加多个镂空。
路径与复杂形状
g.moveTo(50, 50)
.lineTo(200, 50)
.bezierCurveTo(250, 100, 250, 150, 200, 200)
.quadraticCurveTo(100, 250, 50, 200)
.closePath()
.fill({ color: 0x6c5ce7, alpha: 0.7 })
.stroke({ width: 2, color: 0xdfe6e9 });
路径方法:moveTo、lineTo、bezierCurveTo、quadraticCurveTo、arc、arcTo、arcToSvg、closePath。调用 beginPath() 可丢弃当前路径并开始新路径。
// arc(cx, cy, radius, startAngle, endAngle, counterclockwise?)
g.moveTo(80, 50)
.arc(50, 50, 30, 0, Math.PI)
.stroke({ width: 4, color: 0x2c3e50 });
// arcTo(x1, y1, x2, y2, radius) — rounded corner between two line segments
g.moveTo(150, 20)
.arcTo(200, 20, 200, 80, 20)
.lineTo(200, 80)
.stroke({ width: 2 });
// arcToSvg(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) — matches the SVG `A` command
g.moveTo(250, 50).arcToSvg(40, 20, 0, 1, 0, 330, 50).stroke({ width: 2 });
渐变和图案
// Linear gradient
const linear = new FillGradient({
end: { x: 1, y: 0 },
colorStops: [
{ offset: 0, color: 0xff0000 },
{ offset: 1, color: 0x0000ff },
],
});
g.rect(0, 0, 200, 100).fill(linear);
// Radial gradient. Coordinates are normalized 0-1 in the default "local" space:
// inner circle at the center, outer circle reaching the edges.
const radial = new FillGradient({
type: "radial",
center: { x: 0.5, y: 0.5 },
innerRadius: 0,
outerCenter: { x: 0.5, y: 0.5 },
outerRadius: 0.5,
colorStops: [
{ offset: 0, color: 0xffffff },
{ offset: 1, color: 0x000000 },
],
});
g.circle(100, 100, 100).fill(radial);
// Pixel coordinates need textureSpace: "global"; the gradient then spans shapes.
const shared = new FillGradient({
type: "radial",
center: { x: 100, y: 100 },
outerRadius: 100,
textureSpace: "global",
colorStops: [
{ offset: 0, color: 0xffffff },
{ offset: 1, color: 0x000000 },
],
});
g.rect(0, 0, 200, 200).fill(shared);
const brick = await Assets.load("brick.png");
// Options-object form (preferred)
const pattern = new FillPattern({
texture: brick,
repetition: "repeat", // 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'
textureSpace: "global", // 'global' (default) | 'local'
});
// Legacy positional form is still supported
const pattern2 = new FillPattern(brick, "repeat");
g.rect(0, 120, 200, 100).fill(pattern);
FillGradient 的默认 type 为 'linear',起点为 {0,0},终点为 {0,1}(垂直)。径向渐变可将 type 设为 'radial',并设置 center/innerRadius 和 outerCenter/outerRadius;rotation(弧度,默认值为 0)和 scale(默认值为 1)可使渐变呈椭圆形,且仅适用于 Graphics。textureSpace 默认为 'local'(归一化的 0-1 形状坐标);使用 'global' 可在多个形状间共享像素坐标。
FillPattern 接受一个选项对象({ texture, repetition?, textureSpace? })或旧版的位置参数形式(new FillPattern(texture, repetition?))。repetition 用于选择平铺模式。textureSpace 控制图块如何映射到形状:
'global'(默认):图块在Graphics坐标系中连续重复,因此相邻形状共享同一平铺网格。最适合背景和无缝纹理。'local':单个图块适配每个形状的边界。与setTransform配合,可将形状细分为图块网格。
请注意,FillPattern 的 textureSpace 默认值为 'global',与上文所示纹理填充的 'local' 默认值不同。
setTransform(matrix) 会将给定矩阵直接复制到图案变换中,以缩放、旋转或偏移平铺;不带参数调用 setTransform() 可将其重置为单位变换。
请在 FillPattern 本身上设置 textureSpace 和变换。将图案传入样式对象时(fill({ fill: pattern, textureSpace: "local" })),图案自身的值会覆盖样式的 textureSpace 和 matrix。
直接绘制纹理
const tex = await Assets.load("icon.png");
// Draw the whole texture at (x, y) with optional tint
g.texture(tex, 0xffffff, 20, 20);
// Draw a subregion (dx, dy, dw, dh)
g.texture(tex, 0xff0000, 100, 20, 64, 64);
Graphics.texture(texture, tint?, dx?, dy?, dw?, dh?) 是一种快捷方式,无需通过 fill() 即可绘制单个带纹理的矩形。适用于不需要完整精灵生命周期的图标。
GraphicsContext 共享
const ctx = new GraphicsContext().rect(0, 0, 50, 50).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx);
g2.x = 100;
共享上下文可避免重复生成 GPU 几何数据;耗时的镶嵌处理只会运行一次。也可以在构造后指定上下文:g.context = existingContext。
SVG 导入和导出
使用 svg() 将 SVG 标记解析到当前上下文中:
g.svg(`<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="red"/>
</svg>`);
svg() 可解析 <path>(包括 fill-rule="evenodd" 镂空)、<rect>、<circle>、<ellipse>、<line>、<polygon>、<polyline> 和 <g> 分组。样式可通过属性或内联 style 中的 fill、stroke、stroke-width、fill-opacity、stroke-opacity 和 opacity 指定。<defs> 中的 <linearGradient> 和 <radialGradient> 定义会转换为 FillGradient,并通过 url(#id) 应用;gradientUnits 会映射到 textureSpace,且支持百分比坐标。不支持:transform 属性、<style> 块、stroke-linecap/stroke-linejoin/stroke-dasharray、gradientTransform、spreadMethod、stop-opacity、<text>、<image>、<use>、<clipPath>、<mask>、<pattern>。遇到不支持的元素时会记录警告并跳过。由于 Pixi 的三角剖分经过性能优化,复杂的镂空几何图形可能渲染不准确。
使用 graphicsContextToSvg 将 Graphics 或 GraphicsContext 序列化为独立的 SVG 文档字符串:
import { Graphics, graphicsContextToSvg } from "pixi.js";
const g = new Graphics()
.rect(0, 0, 100, 50)
.fill({ color: 0xff0000 })
.circle(150, 25, 25)
.stroke({ color: 0x0000ff, width: 4 });
const svgString = graphicsContextToSvg(g, 2);
graphicsContextToSvg(source, precision = 2) 是一个纯函数,会读取上下文的指令,并返回包含自动计算的 viewBox 的完整 <svg> 字符串。传入 Graphics 或 GraphicsContext;precision 用于控制输出坐标的小数位数。它会导出所有形状填充图元(regularPoly/filletRect 等高级图形会回退为形状路径)、所有路径方法、描边属性(width、cap、join、miterLimit)、fill-opacity/stroke-opacity,以及通过 <defs> 块导出的 FillGradient(线性和径向)。镂空会合并为一个带有 fill-rule="evenodd" 的 <path>。FillPattern 和纹理填充没有对应的 SVG 表示:图案会回退为填充的纯色 color,而 texture() 指令会被完全跳过。导出的标记可直接通过 g.svg(...) 重新导入,无需清理,因此你可以导出、保存图形,并在之后将其重新导入另一个 Graphics。
重用 GraphicsPath
const arrow = new GraphicsPath()
.moveTo(0, 0)
.lineTo(40, 0)
.lineTo(40, -10)
.lineTo(60, 10)
.lineTo(40, 30)
.lineTo(40, 20)
.lineTo(0, 20)
.closePath();
g.path(arrow).fill(0x3498db);
g.translateTransform(80, 0).path(arrow).fill(0xe74c3c);
Graphics.path(graphicsPath)(以及 GraphicsContext.path())会将预先构建的 GraphicsPath 追加到当前路径中。构建一次,绘制多次。
绘制时变换
Graphics 有自己的绘制时变换堆栈,与应用于渲染输出的 Container 变换分开。绘制变换方法已重命名,以避免与 Container.rotation、Container.scale、Container.position 冲突:
| 绘制变换 | Container 变换 |
|---|---|
g.rotateTransform(angle) | g.rotation |
g.scaleTransform(x, y?) | g.scale.set(x, y) |
g.translateTransform(x, y?) | g.position.set(x, y) |
g.setTransform(matrix) 或 setTransform(a,b,c,d,tx,ty) | g.setFromMatrix(matrix) |
g.transform(matrix) 或 transform(a,b,c,d,tx,ty) | 不适用 |
g.getTransform() / g.resetTransform() | 不适用 |
const g = new Graphics();
g.translateTransform(100, 100)
.rotateTransform(Math.PI / 4)
.rect(-25, -25, 50, 50)
.fill(0x3498db);
// The square is rotated 45 degrees as it is added to the geometry.
// Setting g.rotation later rotates the entire Graphics on screen.
绘制变换会影响之后添加到上下文中的每个形状和路径命令。使用 save()/restore() 对其进行作用域控制。
状态保存与恢复
g.save();
g.translateTransform(100, 100);
g.rotateTransform(Math.PI / 4);
g.rect(0, 0, 50, 50).fill(0xff0000);
g.restore();
save() 会将绘制变换、填充样式和描边样式压入堆栈;restore() 会将它们弹出。Graphics 直接提供 save/restore 方法,对应底层 GraphicsContext 的调用。
通过 setFillStyle / setStrokeStyle 设置默认样式
g.setFillStyle({ color: 0x3498db, alpha: 0.8 }).setStrokeStyle({
width: 2,
color: 0x2c3e50,
});
g.rect(0, 0, 100, 100).fill().stroke();
g.circle(150, 50, 40).fill().stroke();
setFillStyle() 和 setStrokeStyle() 用于配置后续未传入参数的 fill() / stroke() 调用所使用的默认样式。你可以随时通过 fillStyle 和 strokeStyle getter/setter 读取或替换当前样式。启动时修改 GraphicsContext.defaultFillStyle 和 GraphicsContext.defaultStrokeStyle,即可覆盖整个库的默认值。
命中测试
const g = new Graphics().star(100, 100, 5, 60, 30).fill(0xf39c12);
g.eventMode = "static";
g.on("pointermove", (e) => {
if (g.containsPoint(g.toLocal(e.global))) {
/* over the star, not just its bbox */
}
});
Graphics.containsPoint(pointInLocalSpace) 会对上下文中的每个填充和描边形状执行考虑拓扑结构的测试,包括孔洞。请先通过 toLocal() 转换全局指针坐标。描边形状的命中测试针对实际绘制的描边进行:命中范围取决于描边的 width 和 alignment(1 表示向内,0.5 表示居中,0 表示向外),且与多边形的绕序无关。
克隆、清除和边界
const g = new Graphics().rect(0, 0, 100, 100).fill(0xff0000);
const shallow = g.clone(); // shares the same GraphicsContext
const deep = g.clone(true); // creates an independent context
console.log(g.bounds.width); // 100 - geometry bounds before transforms
g.clear(); // wipes active path, instructions, and transform; fill/stroke styles persist
clone()会返回一个新的Graphics,并与源对象共享上下文(开销较低,复用几何数据)。如果上下文发生变化,这两个对象都会随之更新。clone(true)也会克隆上下文,因此新Graphics可以独立编辑。bounds返回Container变换前的几何边界,可用于布局决策。clear()会重置上下文,以便重复使用同一个Graphics。关于何时清除、何时保留稳定几何数据,请参阅下文的常见错误。
GraphicsContext 工具
| 成员 | 行为 |
|---|---|
ctx.path(graphicsPath) | 将预先构建的 GraphicsPath 应用到当前活动路径。可在多个上下文或帧中复用同一个路径。 |
ctx.beginPath() | 丢弃当前活动路径并开始新路径,不影响已提交的指令。 |
ctx.setFillStyle(style) / ctx.fillStyle | 设置或读取后续形状使用的默认填充样式,无需调用 fill()。 |
ctx.setStrokeStyle(style) / ctx.strokeStyle | 设置或读取后续形状使用的默认描边样式,无需调用 stroke()。 |
ctx.bounds | 缓存所有填充、描边和纹理指令的几何边界。 |
ctx.clear() | 清除指令、活动路径和绘图变换。 |
ctx.clone() | 深拷贝指令、活动路径、变换、样式和堆栈。 |
ctx.containsPoint(point) | 对所有填充和描边形状执行考虑拓扑结构的命中测试(包括孔洞)。 |
ctx.batchMode | 可设为 'auto'、'batch' 或 'no-batch',以强制启用或禁用此上下文中形状的批处理。 |
ctx.customShader | 指定一个 Shader,以覆盖默认图形着色器。 |
GraphicsContext.defaultFillStyle | 调用 fill() 时未传入参数且未设置填充样式时使用的静态回退值。 |
GraphicsContext.defaultStrokeStyle | 调用 stroke() 时未传入参数且未设置描边样式时使用的静态回退值。 |
GraphicsContext 是一个 EventEmitter,会触发 update、destroy 和 unload 事件。当工具或对象池需要响应上下文生命周期变化时,可通过 ctx.on('update' | 'destroy' | 'unload', cb) 订阅这些事件。
常见错误
[CRITICAL] 使用 v7 的 beginFill/drawRect/endFill
错误:
const g = new Graphics().beginFill(0xff0000).drawRect(0, 0, 100, 100).endFill();
正确:
const g = new Graphics().rect(0, 0, 100, 100).fill(0xff0000);
v8 将“设置样式、绘制、结束”替换为“绘制形状,然后应用样式”。beginFill/endFill 不存在。
[CRITICAL] 使用旧的形状方法名称
错误:
g.drawCircle(50, 50, 25);
正确:
g.circle(50, 50, 25);
v8 重命名了所有 draw* 方法:drawRect → rect、drawCircle → circle、drawEllipse → ellipse、drawPolygon → poly、drawRoundedRect → roundRect、drawStar → star。
[CRITICAL] 使用 lineStyle 而不是 stroke
错误:
g.lineStyle(2, 0xffffff);
g.drawRect(0, 0, 100, 100);
正确:
g.rect(0, 0, 100, 100).stroke({ width: 2, color: 0xffffff });
lineStyle 已被移除。绘制形状后使用 stroke()。描边选项对象接受 width、color、alpha、cap、join、alignment、miterLimit 和 pixelLine。
[HIGH] 使用 beginHole/endHole 创建孔洞
错误:
g.beginFill(0x00ff00)
.drawRect(0, 0, 100, 100)
.beginHole()
.drawCircle(50, 50, 20)
.endHole()
.endFill();
正确:
g.rect(0, 0, 100, 100).fill(0x00ff00).circle(50, 50, 20).cut();
beginHole/endHole 已被 cut() 替代。绘制外部形状并填充,然后绘制孔洞形状并调用 cut()。
[HIGH] 使用 GraphicsGeometry 而不是 GraphicsContext
错误:
const geom = g.geometry;
const clone = new Graphics(geom);
正确:
const ctx = new GraphicsContext().rect(0, 0, 100, 100).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx);
在 v8 中,GraphicsGeometry 已被 GraphicsContext 替代。不存在 .geometry 属性。
[HIGH] 意外销毁共享的 GraphicsContext
const ctx = new GraphicsContext().rect(0, 0, 50, 50).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx);
g1.destroy({ context: true }); // g2 is left holding a destroyed context
销毁共享的 GraphicsContext 不会销毁其他使用它的 Graphics,但它们仍会保留对已销毁上下文的引用,导致无法继续正确更新或渲染。通过构造函数传入上下文时,不带参数调用 destroy() 会保留上下文,并将实例与上下文分离;也可以使用 destroy({ context: false }) 明确指定。只有在所有共享实例都不再使用该上下文时,才销毁它。自行拥有的上下文(未通过构造函数传入)仍会在不带参数调用 destroy() 时被销毁。
[HIGH] 每帧清除并重新绘制 Graphics
Graphics 旨在保持稳定,而非动态。每帧调用 clear() 并重新绘制都会重新构建 GPU 几何体。对于动态视觉效果:
- 使用预渲染纹理并通过变换进行更改的
Sprite。 - 对复杂的静态图形使用
cacheAsTexture(true)。 - 对于实时形状变化,可考虑使用自定义几何体更新的
Mesh。
这与 HTML Canvas 2D 正好相反,在 HTML Canvas 2D 中,每帧重绘很常见。PixiJS 会将形状细分为 GPU 三角形,因此初次绘制开销较大,但后续渲染速度很快。应将 Graphics 视为 SVG 元素,而不是 Canvas 绘图调用。
[MEDIUM] 不要在 Graphics 中嵌套子项
Graphics 将 allowChildren 设为 false。添加子项会记录弃用警告,并会在未来版本中成为严重错误。将多个图形与其他叶节点一起包在普通的 Container 中:
const group = new Container();
group.addChild(graphics, sprite);