You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PIXI.js代码占用大量内存致Chrome崩溃,求高效重复绘图方案

问题分析与优化方案

你的代码导致Chrome内存占用到1.5G后崩溃的原因其实很好理解:每次调用graphics.drawRect()都会在PIXI.Graphics对象中累积新的绘制指令。随着app.ticker每帧执行render函数,这些指令会无限制地堆积——毕竟每一个小矩形的绘制坐标、尺寸、颜色信息都被完整保存在内存里,最终直接撑爆内存。

下面根据不同的需求场景,给你几种高效的优化方案:

方案1:仅显示单个动态矩形(最轻量化)

如果你的需求只是让一个3x3的矩形随机切换位置,不需要保留历史绘制的所有矩形,那每次渲染前清空Graphics的绘制指令就行:

const width = window.innerWidth; 
const height = window.innerHeight; 
const app = new PIXI.Application({ width, height }); 
const graphics = new PIXI.Graphics(); 
app.stage.addChild(graphics); 

app.loader.load(setup); 

function setup() { 
  document.body.appendChild(app.view); 
  app.ticker.add(render); 
} 

function render() { 
  // 关键步骤:清空之前所有的绘制指令
  graphics.clear();
  // 清空后需要重新设置填充色
  graphics.beginFill(16763904);
  const x = randomInt(0, width - 3); // 减去方块宽度,避免超出屏幕边缘
  const y = randomInt(0, height - 3); 
  graphics.drawRect(x, y, 3, 3); 
  graphics.endFill(); // 可选,养成良好习惯
} 

function randomInt(min, max) { 
  return Math.floor(Math.random() * (max - min + 1)) + min; 
}

方案2:保留大量矩形(推荐最优方案)

如果需要保留所有绘制过的矩形,PIXI.Graphics的累积式绘制肯定不行,推荐用**PIXI.ParticleContainer + 预生成纹理**的组合——这是PIXI里渲染大量相同元素的效率天花板:

const width = window.innerWidth; 
const height = window.innerHeight; 
const app = new PIXI.Application({ width, height }); 

// 预先生成一个3x3红色方块的纹理(所有矩形共用这个纹理)
const texture = PIXI.RenderTexture.create({ width: 3, height: 3 });
const tempGraphics = new PIXI.Graphics();
tempGraphics.beginFill(16763904);
tempGraphics.drawRect(0, 0, 3, 3);
tempGraphics.endFill();
// 把临时Graphics的内容渲染到纹理上
app.renderer.render(tempGraphics, { renderTexture: texture });
tempGraphics.destroy(); // 用完临时对象立刻销毁,释放内存

// 使用ParticleContainer,比普通Container高效N倍,专门用来批量处理大量相同元素
const particleContainer = new PIXI.ParticleContainer(10000, { 
  position: true, // 只开启我们需要的属性,进一步优化性能
  scale: false,
  rotation: false,
  alpha: false
});
app.stage.addChild(particleContainer);

app.loader.load(setup); 

function setup() { 
  document.body.appendChild(app.view); 
  app.ticker.add(render); 
} 

function render() { 
  const x = randomInt(0, width - 3); 
  const y = randomInt(0, height - 3); 
  // 创建一个使用预生成纹理的Sprite
  const rectSprite = new PIXI.Sprite(texture);
  rectSprite.position.set(x, y);
  particleContainer.addChild(rectSprite);

  // 可选:如果不想让元素无限增加,可以限制总数,移除最早的元素
  // if (particleContainer.children.length > 10000) {
  //   particleContainer.removeChildAt(0);
  // }
} 

function randomInt(min, max) { 
  return Math.floor(Math.random() * (max - min + 1)) + min; 
}

为什么这个方案高效?

  • ParticleContainer会把所有子元素的位置数据打包成GPU能批量处理的缓冲区,大幅减少CPU和GPU之间的通信开销。
  • 所有矩形共用同一个纹理,避免了重复的纹理加载与绑定,内存占用会比Graphics方式低几个数量级。

方案3:Canvas纹理动态绘制(适合中等数量场景)

如果你的矩形数量没到十万级,只是几千个左右,也可以用Canvas作为绘制载体,再把Canvas转为PIXI纹理来渲染:

const width = window.innerWidth; 
const height = window.innerHeight; 
const app = new PIXI.Application({ width, height }); 

// 创建一个和窗口一样大的Canvas
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#FF5500'; // 对应你用的颜色值16763904

// 将Canvas转为PIXI纹理,生成Sprite添加到舞台
const canvasTexture = PIXI.Texture.from(canvas);
const canvasSprite = new PIXI.Sprite(canvasTexture);
app.stage.addChild(canvasSprite);

app.loader.load(setup); 

function setup() { 
  document.body.appendChild(app.view); 
  app.ticker.add(render); 
} 

function render() { 
  const x = randomInt(0, width); 
  const y = randomInt(0, height); 
  // 在Canvas上画矩形
  ctx.fillRect(x, y, 3, 3);
  // 通知PIXI纹理已更新,让舞台重新渲染
  canvasTexture.update();
} 

function randomInt(min, max) { 
  return Math.floor(Math.random() * (max - min + 1)) + min; 
}

这个方案实现起来更简单,内存占用比Graphics低,但性能不如ParticleContainer,适合中等数量的场景。

内容的提问来源于stack exchange,提问作者Bulkan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:22:50