PixiJS 图形绘制 #
Graphics 概述 #
Graphics 是 PixiJS 中用于绘制矢量图形的类,它提供了一套简单易用的 API 来创建各种形状。
text
┌─────────────────────────────────────────────────────────────┐
│ Graphics 功能 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 基本形状 │
│ ├── 矩形 (rect) │
│ ├── 圆角矩形 (roundRect) │
│ ├── 圆形 (circle) │
│ └── 椭圆 (ellipse) │
│ │
│ 复杂形状 │
│ ├── 多边形 (poly) │
│ ├── 路径 (moveTo, lineTo) │
│ └── 弧线 (arc, arcTo) │
│ │
│ 样式设置 │
│ ├── 填充 (fill) │
│ ├── 描边 (stroke) │
│ └── 线条样式 │
│ │
└─────────────────────────────────────────────────────────────┘
创建 Graphics #
基本创建 #
javascript
import { Graphics } from 'pixi.js';
const graphics = new Graphics();
app.stage.addChild(graphics);
绘制流程 #
text
┌─────────────────────────────────────────────────────────────┐
│ 绘制流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 清除(可选) │
│ graphics.clear() │
│ │
│ 2. 定义形状 │
│ graphics.rect(0, 0, 100, 100) │
│ │
│ 3. 设置样式 │
│ graphics.fill({ color: 0xff0000 }) │
│ │
│ 4. 添加到舞台 │
│ app.stage.addChild(graphics) │
│ │
└─────────────────────────────────────────────────────────────┘
基本形状 #
矩形 #
javascript
const graphics = new Graphics();
// 基本矩形
graphics.rect(50, 50, 100, 80);
graphics.fill({ color: 0xff0000 });
// 圆角矩形
graphics.roundRect(200, 50, 100, 80, 10);
graphics.fill({ color: 0x00ff00 });
// 多个矩形
graphics.rect(50, 200, 50, 50);
graphics.rect(120, 200, 50, 50);
graphics.rect(190, 200, 50, 50);
graphics.fill({ color: 0x0000ff });
app.stage.addChild(graphics);
圆形 #
javascript
const graphics = new Graphics();
// 基本圆形
graphics.circle(100, 100, 50);
graphics.fill({ color: 0xff0000 });
// 圆形描边
graphics.circle(250, 100, 50);
graphics.stroke({ width: 3, color: 0x00ff00 });
// 多个圆形
for (let i = 0; i < 5; i++) {
graphics.circle(100 + i * 80, 250, 30);
graphics.fill({ color: 0x0000ff + i * 0x001100 });
}
app.stage.addChild(graphics);
椭圆 #
javascript
const graphics = new Graphics();
// 基本椭圆
graphics.ellipse(150, 100, 80, 50);
graphics.fill({ color: 0xff9900 });
// 垂直椭圆
graphics.ellipse(350, 100, 50, 80);
graphics.fill({ color: 0x0099ff });
app.stage.addChild(graphics);
多边形 #
javascript
const graphics = new Graphics();
// 三角形
graphics.poly([100, 50, 150, 150, 50, 150]);
graphics.fill({ color: 0xff0000 });
// 五边形
const sides = 5;
const radius = 50;
const centerX = 300;
const centerY = 100;
const points = [];
for (let i = 0; i < sides; i++) {
const angle = (i / sides) * Math.PI * 2 - Math.PI / 2;
points.push(
centerX + Math.cos(angle) * radius,
centerY + Math.sin(angle) * radius
);
}
graphics.poly(points);
graphics.fill({ color: 0x00ff00 });
// 星形
graphics.star(500, 100, 5, 50, 25);
graphics.fill({ color: 0xffff00 });
app.stage.addChild(graphics);
路径绘制 #
基本路径 #
javascript
const graphics = new Graphics();
// 移动起点
graphics.moveTo(50, 50);
// 画线到点
graphics.lineTo(150, 50);
graphics.lineTo(150, 150);
graphics.lineTo(50, 150);
// 闭合路径
graphics.closePath();
// 描边
graphics.stroke({ width: 2, color: 0xff0000 });
app.stage.addChild(graphics);
复杂路径 #
javascript
const graphics = new Graphics();
// 绘制箭头
graphics.moveTo(100, 50);
graphics.lineTo(150, 100);
graphics.lineTo(125, 100);
graphics.lineTo(125, 150);
graphics.lineTo(75, 150);
graphics.lineTo(75, 100);
graphics.lineTo(50, 100);
graphics.closePath();
graphics.fill({ color: 0x3366ff });
app.stage.addChild(graphics);
弧线 #
javascript
const graphics = new Graphics();
// 圆弧
graphics.arc(100, 100, 50, 0, Math.PI);
graphics.stroke({ width: 2, color: 0xff0000 });
// 完整圆
graphics.arc(250, 100, 50, 0, Math.PI * 2);
graphics.stroke({ width: 2, color: 0x00ff00 });
// 弧形填充(饼图效果)
graphics.moveTo(400, 100);
graphics.arc(400, 100, 50, 0, Math.PI * 1.5);
graphics.closePath();
graphics.fill({ color: 0x0000ff });
app.stage.addChild(graphics);
样式设置 #
填充样式 #
javascript
const graphics = new Graphics();
// 纯色填充
graphics.rect(50, 50, 80, 60);
graphics.fill({ color: 0xff0000 });
// 带透明度的填充
graphics.rect(150, 50, 80, 60);
graphics.fill({ color: 0x00ff00, alpha: 0.5 });
// 渐变填充(需要使用 Texture)
const gradientTexture = createGradientTexture();
graphics.rect(250, 50, 80, 60);
graphics.fill({ texture: gradientTexture });
app.stage.addChild(graphics);
描边样式 #
javascript
const graphics = new Graphics();
// 基本描边
graphics.rect(50, 50, 80, 60);
graphics.stroke({ width: 2, color: 0xff0000 });
// 粗描边
graphics.rect(150, 50, 80, 60);
graphics.stroke({ width: 5, color: 0x00ff00 });
// 带透明度的描边
graphics.rect(250, 50, 80, 60);
graphics.stroke({ width: 3, color: 0x0000ff, alpha: 0.5 });
app.stage.addChild(graphics);
线条端点和连接 #
javascript
const graphics = new Graphics();
// 设置线条样式
graphics.rect(50, 50, 80, 60);
graphics.stroke({
width: 10,
color: 0xff0000,
alpha: 1,
alignment: 0.5, // 0-1,线条对齐方式
native: false // 是否使用原生线条
});
app.stage.addChild(graphics);
填充与描边组合 #
同时填充和描边 #
javascript
const graphics = new Graphics();
// 先填充后描边
graphics.circle(100, 100, 50);
graphics.fill({ color: 0xff9900 });
graphics.stroke({ width: 3, color: 0xff0000 });
// 多个形状
graphics.rect(200, 50, 100, 100);
graphics.fill({ color: 0x00ff00 });
graphics.stroke({ width: 2, color: 0x006600 });
app.stage.addChild(graphics);
分开绘制 #
javascript
const graphics = new Graphics();
// 填充形状
graphics.circle(100, 100, 50);
graphics.fill({ color: 0xff9900 });
// 描边形状(需要新路径)
graphics.circle(100, 100, 50);
graphics.stroke({ width: 3, color: 0xff0000 });
app.stage.addChild(graphics);
清除和重绘 #
清除图形 #
javascript
const graphics = new Graphics();
// 清除所有图形
graphics.clear();
// 清除后重新绘制
graphics.rect(50, 50, 100, 100);
graphics.fill({ color: 0xff0000 });
动态更新 #
javascript
const graphics = new Graphics();
app.stage.addChild(graphics);
let angle = 0;
app.ticker.add(() => {
graphics.clear();
// 绘制旋转的矩形
graphics.rect(-50, -50, 100, 100);
graphics.fill({ color: 0xff0000 });
graphics.rotation = angle;
graphics.position.set(400, 300);
angle += 0.01;
});
高级技巧 #
绘制网格 #
javascript
function drawGrid(graphics, width, height, cellSize, color) {
graphics.clear();
// 垂直线
for (let x = 0; x <= width; x += cellSize) {
graphics.moveTo(x, 0);
graphics.lineTo(x, height);
}
// 水平线
for (let y = 0; y <= height; y += cellSize) {
graphics.moveTo(0, y);
graphics.lineTo(width, y);
}
graphics.stroke({ width: 1, color, alpha: 0.3 });
return graphics;
}
const grid = drawGrid(new Graphics(), 800, 600, 50, 0xffffff);
app.stage.addChild(grid);
绘制圆环 #
javascript
function drawRing(graphics, x, y, innerRadius, outerRadius, color) {
graphics.clear();
// 外圆
graphics.circle(x, y, outerRadius);
graphics.fill({ color });
// 内圆(镂空)
graphics.circle(x, y, innerRadius);
graphics.fill({ color: 0x000000, alpha: 0 });
return graphics;
}
const ring = drawRing(new Graphics(), 400, 300, 40, 60, 0xff9900);
app.stage.addChild(ring);
绘制进度条 #
javascript
class ProgressBar extends Graphics {
constructor(width, height, backgroundColor, fillColor) {
super();
this.barWidth = width;
this.barHeight = height;
this.backgroundColor = backgroundColor;
this.fillColor = fillColor;
this._progress = 0;
this.draw();
}
get progress() {
return this._progress;
}
set progress(value) {
this._progress = Math.max(0, Math.min(1, value));
this.draw();
}
draw() {
this.clear();
// 背景
this.roundRect(0, 0, this.barWidth, this.barHeight, 5);
this.fill({ color: this.backgroundColor });
// 进度
if (this._progress > 0) {
const fillWidth = this.barWidth * this._progress;
this.roundRect(0, 0, fillWidth, this.barHeight, 5);
this.fill({ color: this.fillColor });
}
}
}
const progressBar = new ProgressBar(300, 30, 0x333333, 0x00ff00);
progressBar.x = 250;
progressBar.y = 300;
app.stage.addChild(progressBar);
// 更新进度
progressBar.progress = 0.75;
绘制图表 #
javascript
function drawBarChart(data, x, y, width, height) {
const graphics = new Graphics();
const maxValue = Math.max(...data.map(d => d.value));
const barWidth = width / data.length - 10;
data.forEach((item, index) => {
const barHeight = (item.value / maxValue) * height;
const barX = x + index * (barWidth + 10);
const barY = y + height - barHeight;
graphics.rect(barX, barY, barWidth, barHeight);
graphics.fill({ color: item.color });
});
return graphics;
}
const chart = drawBarChart([
{ value: 100, color: 0xff0000 },
{ value: 200, color: 0x00ff00 },
{ value: 150, color: 0x0000ff },
{ value: 180, color: 0xffff00 }
], 100, 100, 400, 200);
app.stage.addChild(chart);
绘制雷达图 #
javascript
function drawRadarChart(centerX, centerY, radius, values, labels) {
const graphics = new Graphics();
const sides = values.length;
const angleStep = (Math.PI * 2) / sides;
// 绘制背景网格
for (let r = 0.2; r <= 1; r += 0.2) {
const points = [];
for (let i = 0; i < sides; i++) {
const angle = angleStep * i - Math.PI / 2;
points.push(
centerX + Math.cos(angle) * radius * r,
centerY + Math.sin(angle) * radius * r
);
}
graphics.poly(points);
graphics.stroke({ width: 1, color: 0x666666, alpha: 0.5 });
}
// 绘制轴线
for (let i = 0; i < sides; i++) {
const angle = angleStep * i - Math.PI / 2;
graphics.moveTo(centerX, centerY);
graphics.lineTo(
centerX + Math.cos(angle) * radius,
centerY + Math.sin(angle) * radius
);
}
graphics.stroke({ width: 1, color: 0x666666, alpha: 0.5 });
// 绘制数据区域
const dataPoints = [];
for (let i = 0; i < sides; i++) {
const angle = angleStep * i - Math.PI / 2;
const value = values[i] / 100;
dataPoints.push(
centerX + Math.cos(angle) * radius * value,
centerY + Math.sin(angle) * radius * value
);
}
graphics.poly(dataPoints);
graphics.fill({ color: 0x00ff00, alpha: 0.3 });
graphics.stroke({ width: 2, color: 0x00ff00 });
return graphics;
}
const radar = drawRadarChart(400, 300, 150, [80, 60, 90, 70, 85], []);
app.stage.addChild(radar);
性能优化 #
使用 Graphics 缓存 #
javascript
const graphics = new Graphics();
// 绘制复杂图形
graphics.rect(0, 0, 100, 100);
graphics.fill({ color: 0xff0000 });
// 缓存为位图
graphics.cacheAsBitmap = true;
// 这将提高渲染性能,但会增加内存使用
批量绘制 #
javascript
// 不推荐:多次绘制
for (let i = 0; i < 100; i++) {
const g = new Graphics();
g.circle(Math.random() * 800, Math.random() * 600, 5);
g.fill({ color: 0xff0000 });
app.stage.addChild(g);
}
// 推荐:单个 Graphics 绘制多个形状
const graphics = new Graphics();
for (let i = 0; i < 100; i++) {
graphics.circle(Math.random() * 800, Math.random() * 600, 5);
}
graphics.fill({ color: 0xff0000 });
app.stage.addChild(graphics);
避免频繁清除 #
javascript
// 不推荐:每帧清除重绘
app.ticker.add(() => {
graphics.clear();
graphics.circle(x, y, 50);
graphics.fill({ color: 0xff0000 });
});
// 推荐:使用变换而非重绘
const circle = new Graphics();
circle.circle(0, 0, 50);
circle.fill({ color: 0xff0000 });
app.stage.addChild(circle);
app.ticker.add(() => {
circle.position.set(x, y);
});
实战示例 #
绘制按钮 #
javascript
class Button extends Graphics {
constructor(text, width = 150, height = 50) {
super();
this.buttonWidth = width;
this.buttonHeight = height;
this.text = text;
this.isHovered = false;
this.eventMode = 'static';
this.cursor = 'pointer';
this.on('pointerover', () => this.onHover(true));
this.on('pointerout', () => this.onHover(false));
this.draw();
}
onHover(hovered) {
this.isHovered = hovered;
this.draw();
}
draw() {
this.clear();
const bgColor = this.isHovered ? 0x4488ff : 0x3366cc;
this.roundRect(0, 0, this.buttonWidth, this.buttonHeight, 8);
this.fill({ color: bgColor });
// 添加文字需要单独的 Text 对象
}
}
const button = new Button('Click Me');
button.x = 325;
button.y = 275;
app.stage.addChild(button);
绘制仪表盘 #
javascript
class Gauge extends Graphics {
constructor(radius, minValue, maxValue) {
super();
this.radius = radius;
this.minValue = minValue;
this.maxValue = maxValue;
this._value = minValue;
this.draw();
}
get value() {
return this._value;
}
set value(val) {
this._value = Math.max(this.minValue, Math.min(this.maxValue, val));
this.draw();
}
draw() {
this.clear();
// 背景弧
this.arc(0, 0, this.radius, Math.PI * 0.75, Math.PI * 2.25);
this.stroke({ width: 20, color: 0x333333 });
// 值弧
const progress = (this._value - this.minValue) / (this.maxValue - this.minValue);
const endAngle = Math.PI * 0.75 + progress * Math.PI * 1.5;
this.arc(0, 0, this.radius, Math.PI * 0.75, endAngle);
this.stroke({ width: 20, color: 0x00ff00 });
}
}
const gauge = new Gauge(80, 0, 100);
gauge.position.set(400, 300);
gauge.value = 75;
app.stage.addChild(gauge);
下一步 #
掌握了图形绘制后,接下来学习 文本处理,了解如何在 PixiJS 中渲染和样式化文本!
最后更新:2026-03-29