是否可以在HTML5.canvas中绘制大量简单的几何图形

is it possible to draw a big number of simple geometric figures in HTML5.canvas?

本文关键字:简单 几何图形 绘制 HTML5 canvas 是否      更新时间:2023-09-26

我有一段很棒的代码。

可以想象,这个想法是绘制一个矩形网格。我想要一个大网格,比如说 100 X 100 或更多。

但是,当我以所需的大小(100X 100)运行这段很棒的代码时,我的浏览器崩溃了。

我怎样才能做到这一点?

*请注意:当我说100X100时,我的意思是矩形的最终数量(10k),而不是画布的大小。

谢谢

function init() {        
    var cnv = get('cnv');
    var ctx = cnv.getContext('2d');
    var ancho = 12; // ancho means width
    var alto = 12;  // alto means height
    ctx.fillStyle = randomRGB();
    for (var i = 0; i < cnv.width; i+= ancho) {
        for (var j = 0; j < cnv.height; j+= alto) {
            //dibujar means to draw, rectangulo means rectangle
            dibujarRectangulo(i+ 1, j+1, ancho, alto, ctx); 
        }
    }
}
function dibujarRectangulo(x, y, ancho, alto, ctx) {
    ctx.rect(x, y, ancho, alto);      
    ctx.fill();
    ctx.closePath();
}  

dibujarRectanglo() 函数调用 rect() 函数,该函数将封闭的矩形子路径添加到当前路径。然后调用 fill() 函数来填充当前路径。然后调用 closePath() 函数来关闭子路径,由于子路径已经关闭,因此它不执行任何操作。

换句话说,第一个 dibujarRectanglo() 函数调用是绘制包含 1 个矩形子路径的路径。第二个调用是绘制包含 2 个矩形子路径的路径。第三个调用是绘制包含 3 个矩形子路径的路径。等等。如果循环调用 dibujarRectanglo() 函数 10000 次,那么总共将绘制 1+2+3+...+10000 = 50005000(即超过 5000 万个)矩形子路径。

dibujarRectangle() 函数每次都应该启动一个新路径。例如。。。

function dibujarRectangulo(x, y, ancho, alto, ctx) {
    ctx.beginPath();
    ctx.rect(x, y, ancho, alto);      
    ctx.fill();
} 
然后 10000

次调用将只绘制 10000 个矩形子路径,这比绘制 5000 万个矩形子路径要快得多。

墙上有16,384个盒子

正如我在评论中所说,画很多盒子很容易,让它们都表现得独特并不容易。无论如何,使用渲染到自身来复制盒子呈指数级,有 128 * 128 个盒子,所以这是 16K,再迭代一次,它将是 64K 盒子。

这是一个作弊,我本可以画随机像素并将每个像素称为一个盒子。

使用画布,您将在使用 FireFox 的高端机器上每帧获得多达 4000 个精灵,每个精灵都有一个位置、中心点、旋转、x 和 y 比例以及一个 alpha 值。但那是机器在全力以赴。

使用WebGL,你可以得到更高的,但代码复杂性会增加。

我使用一般的经验法则,如果一个canva 2D项目有超过1000个精灵,那么它就需要重新设计。

var canvas = document.getElementById("can");
var ctx = canvas.getContext("2d");
/** CreateImage.js begin **/
var createImage = function (w, h) {
    var image = document.createElement("canvas");
    image.width = w;
    image.height = h;
    image.ctx = image.getContext("2d");
    return image;
}
/** CreateImage.js end **/
/** FrameUpdate.js begin **/
var w = canvas.width;
var h = canvas.height;
var cw = w / 2;
var ch = h / 2;
var boxSize = 10;
var boxSizeH = 5;
var timeDiv = 1.2;
var bBSize = boxSize * 128; // back buffer ssize
var buff = createImage(bBSize, bBSize);
var rec = createImage(boxSize, boxSize);
var drawRec = function (ctx, time) {
    var size, x, y;
    size = (Math.sin(time / 200) + 1) * boxSizeH;
    ctx.fillStyle = "hsl(" + Math.floor((Math.sin(time / 500) + 1) * 180) + ",100%,50%)";
    ctx.strokeStyle = "Black";
    ctx.setTransform(1, 0, 0, 1, 0, 0)
    ctx.clearRect(0, 0, boxSize, boxSize);
    x = Math.cos(time / 400);
    y = Math.sin(time / 400);
    ctx.setTransform(x, y, -y, x, boxSizeH, boxSizeH)
    ctx.fillRect(-boxSizeH + size, -boxSizeH + size, boxSize - 2 * size, boxSize - 2 * size);
    ctx.strokeRect(-boxSizeH + size, -boxSizeH + size, boxSize - 2 * size, boxSize - 2 * size);
}
function update(time) {
    var fw, fh, px, py, i;
    time /= 7;
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, w, h);
    drawRec(rec.ctx, time);
    time /= timeDiv;
    buff.ctx.clearRect(0, 0, bBSize, bBSize)
    buff.ctx.drawImage(rec, 0, 0);
    buff.ctx.drawImage(rec, boxSize, 0);
    fw = boxSize + boxSize; // curent copy area width
    fh = boxSize; // curent copy area height
    px = 0; // current copy to x pos
    py = boxSize; // current copy to y pos
    buff.ctx.drawImage(buff, 0, 0, fw, fh, px, py, fw, fh); // make square
    for (i = 0; i < 6; i++) {
        drawRec(rec.ctx, time);
        time /= timeDiv;
        buff.ctx.drawImage(rec, 0, 0);
        fh += fh; // double size across
        px = fw;
        py = 0;
        buff.ctx.drawImage(buff, 0, 0, fw, fh, px, py, fw, fh); // make rec
        drawRec(rec.ctx, time);
        time /= timeDiv;
        buff.ctx.drawImage(rec, 0, 0);
        fw += fw; // double size down
        px = 0;
        py = fh;
        buff.ctx.drawImage(buff, 0, 0, fw, fh, px, py, fw, fh);
    }
    // draw the boxes onto the canvas,
    ctx.drawImage(buff, 0, 0, 1024, 1024);
    requestAnimationFrame(update);
}
update();
.canv {
  width:1024px;
  height:1024px;
}
<canvas id="can" class = "canv" width=1024 height=1024></canvas>