PixiJS 的画格子使用优化

pixijs 是一个开源的 canvas 库,我们可以用这个库来做很多的事情,下面我们要做一个画格子的游戏。

Graphics简单使用

官网上对 graphics 介绍很多,这边不涉及到高级用法,graphics 就是我们用来画格子的。

下面上代码:

javascript 复制代码
const baseWidth = 500
// 声明一个应用
let app = new PIXI.Application({ width: baseWidth, height: baseWidth });

// 声明 graphics,开始画一个5*5的白色矩形
const graphics = new PIXI.Graphics();
graphics.beginFill(0xffffff);
graphics.drawRect(0,0,5,5);

// 添加应用到 dom 中去
app.stage.addChild(graphics);
document.body.appendChild(app.view);

一个哪里够,我要打十个(吹牛的)但是一个格子确实不够,我要画1000个,不对,我要画1000000个

javascript 复制代码
// 格子数
const gridSize = 1000
// gridCount 表示每个格子的宽度,baseWidth表示一个 500 像素大小的 dom
const gridCount = baseWidth / gridSize
for (let x = 0; x < gridSize; x++) {
       for (let y = 0; y < gridSize; y++) {
        graphics.beginFill(0xffffff);
        graphics.drawRect(x * gridCount, y * gridCount, gridCount, gridCount);
    }
 }

颜色就让随机吧

javascript 复制代码
// 生成随机颜色的函数
function getRandomColor() {
   const letters = "0123456789ABCDEF";
   color = "";
   for (let i = 0; i < 6; i++) {
     color += letters[Math.floor(Math.random() * 16)];
   }
   return color;
 }

完整代码:

javascript 复制代码
const baseWidth = 500;
// 格子大小
const gridSize = 1000;
// 每一个格子的大小
const gridCount = baseWidth / gridSize;

let app = new PIXI.Application({ width: baseWidth, height: baseWidth });

const graphics = new PIXI.Graphics();

app.stage.addChild(graphics);
document.body.appendChild(app.view);

draw();

// 生成随机颜色的函数
function getRandomColor() {
   const letters = "0123456789ABCDEF";
   color = "";
   for (let i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
   }
   return color;
}
// 画点
function draw() {
   console.time("draw");
   // 画格子
   for (let x = 0; x < gridSize; x++) {
      for (let y = 0; y < gridSize; y++) {
          graphics.beginFill("0x" + getRandomColor());
          graphics.drawRect(x * gridCount, y * gridCount, gridCount, gridCount);
        }
      }
   console.timeEnd("draw");

   // 渲染
   console.time("render");
   app.render();
   console.timeEnd("render");
   app.stop();
}

最后画的格子大概长这个样子:

书写一个按钮,每次点击就重新画一次吧

ini 复制代码
<button onclick="draw()">画画</button>

渲染卡顿

画完格子了但是卡顿的很,看了一下渲染时间

渲染时间很长?

卡顿原因

研究了一下,每一次使用 graphics 画格子都是递增的,比如在坐标(5,5)画一个绿色格子,然后再在坐标上(5,5)画一个红色格子,并不是修改颜色,而是往上覆盖格子,如图

解决方案

看了官网,没有修改的方法,但是可以通过修改geometry的值来实现。但是每次修改都要使用geometry.invalidate()修正一下数据。尝试了一下,这个方式还是渲染很慢,只是保证了数据不递增而已。当格子数很多的时候,还是会卡顿。

使用精灵

这个问题困扰了很久(救命

大佬出现了,他告诉我可以使用精灵,并且通过纹理来实现,并不是要一定画上去

上代码:

javascript 复制代码
    const buffer = new Uint8Array(gridSize * gridSize * 4);
       for (let x = 0; x < gridSize; x++) {
         for (let y = 0; y < gridSize; y++) {
           const offset = (y + gridSize * x) * 4;
           const color = hexToRGBA(getRandomColor());
           buffer[offset + 0] = color[0]; // R value
           buffer[offset + 1] = color[1]; // G value
           buffer[offset + 2] = color[2]; // B value
           buffer[offset + 3] = 255; // A value
         }
    }
    const texture = PIXI.Texture.fromBuffer(buffer, gridSize, gridSize);
    const sprite = new PIXI.Sprite(texture);
    sprite.x = 0;
    sprite.y = 0;
    sprite.width = baseWidth;
    sprite.height = baseWidth;

    app.stage.removeChildren();
    app.stage.addChild(sprite);

补充方法,将16进制转换为rgba

javascript 复制代码
    function hexToRGBA(hex, alpha = 1) {
       let r = parseInt(hex.slice(1, 3), 16),
       g = parseInt(hex.slice(3, 5), 16),
       b = parseInt(hex.slice(5, 7), 16);

       return [r, g, b, alpha];
    }

具体完整的代码:

javascript 复制代码
     const baseWidth = 500;
     // 格子大小
     const gridSize = 1000;
     // 每一个格子的大小
     const gridCount = baseWidth / gridSize;

     let app = new PIXI.Application({ width: baseWidth, height: baseWidth });


     document.body.appendChild(app.view);

     draw();

     // 生成随机颜色的函数
     function getRandomColor() {
       const letters = "0123456789ABCDEF";
       color = "#";
       for (let i = 0; i < 6; i++) {
         color += letters[Math.floor(Math.random() * 16)];
        }
       return color;
     }

     function hexToRGBA(hex, alpha = 1) {
       let r = parseInt(hex.slice(1, 3), 16),
           g = parseInt(hex.slice(3, 5), 16),
           b = parseInt(hex.slice(5, 7), 16);

          return [r, g, b, alpha];
     }

     // 画点
     function draw() {
       console.time("draw");
       // 画格子
       const buffer = new Uint8Array(gridSize * gridSize * 4);
       for (let x = 0; x < gridSize; x++) {
         for (let y = 0; y < gridSize; y++) {
           const offset = (y + gridSize * x) * 4;
           const color = hexToRGBA(getRandomColor());
           buffer[offset + 0] = color[0]; // R value
           buffer[offset + 1] = color[1]; // G value
           buffer[offset + 2] = color[2]; // B value
           buffer[offset + 3] = 255; // A value
         }
       }
       const texture = PIXI.Texture.fromBuffer(buffer, gridSize, gridSize);
       const sprite = new PIXI.Sprite(texture);
       sprite.x = 0;
       sprite.y = 0;
       sprite.width = baseWidth;
       sprite.height = baseWidth;

       app.stage.removeChildren();
       app.stage.addChild(sprite);

       console.timeEnd("draw");

       // 渲染
       console.time("render");
       app.render();
       console.timeEnd("render");

       app.stop();
    }

渲染时间

这样时间就短了很多了!

相关推荐
哎哟喂_!6 分钟前
Node.js 同步加载问题详解:原理、危害与优化策略
前端·chrome·node.js
__BMGT()8 分钟前
C++ QT图片查看器
前端·c++·qt
OK_boom39 分钟前
React-useRef
javascript·react.js·ecmascript
未来之窗软件服务39 分钟前
solidwors插件 开发————仙盟创梦IDE
前端·javascript·数据库·ide·仙盟创梦ide
小白学大数据1 小时前
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
javascript·redis·分布式·scrapy
Varpb1 小时前
【vue】【环境配置】项目无法npm run serve,显示node版本过低
前端·vue.js·npm
读心悦1 小时前
CSS 溢出内容处理、可见性控制与盒类型设置深度解析
前端·css
Minyy111 小时前
Vue3指令(二)--v-text、v-html数据渲染,计算属性
前端·javascript·vue.js·前端框架·vue·html
个人开发-胡涂涂1 小时前
ECMAScript标准:JavaScript的核心
前端·javascript·ecmascript
GISer_Jing1 小时前
React底层架构深度解析:从虚拟DOM到Fiber的演进之路
前端·react.js·架构