快速调整大型画布元素的大小

时间:2013-03-01 22:29:27

标签: javascript html5-canvas

我制作了一个窗口大小的画布元素并用随机值填充它(以便我可以很容易地看到它更新)。当窗口使用<body onresize="updateCanvas();">时它会调整大小并且速度非常慢。是这样的,或者有更好的方法吗?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Window Sized Canvas</title>
    <!-- <link href="style.css" rel="stylesheet" type="text/css"/>
    Relevant style below: -->
    <style type="text/css">
        body {margin:0; padding:0;}
        canvas {display:block;}
    </style>
</head>
<body onresize="updateCanvas();">
    <canvas id="hCanvas">Your browser does not support the canvas tag</canvas>
    <script type="text/javascript">
        var jCanvas = document.getElementById("hCanvas");
        var jc2D = jCanvas.getContext("2d");

        updateCanvas();
        function updateCanvas() {
            jCanvas.width = window.innerWidth;
            jCanvas.height = window.innerHeight;            
            var jcW = jCanvas.width;
            var jcH = jCanvas.height;
            var jcWH4 = (jcW*jcH)<<2;
            var jcImageData = jc2D.createImageData(jcW, jcH);
            for (i = 0; i < jcWH4; i += 4) {
                jcImageData.data[i] = (Math.random()*255)|0;
                jcImageData.data[i+1] = (Math.random()*255)|0;
                jcImageData.data[i+2] = (Math.random()*255)|0;
                jcImageData.data[i+3] = 255;
            }
            jc2D.putImageData(jcImageData, 0, 0);
        }
    </script>
</body>
</html>

修改:我找到了一些很好的代码来限制onresize()。我将发布与上述不同的内容:

...
<body onresize="resizeTimer();">
...
var resizeDelay;
function resizeTimer() {
    clearTimeout(resizeDelay);
    resizeDelay = setTimeout("updateCanvas()", 200);
}
...

2 个答案:

答案 0 :(得分:2)

此方法比您当前的方法更快!

不是每次调整大小都重新创建随机模式:

  1. 启动时,将随机模式保存一次保存在隐藏的画布(缓冲区)上。

  2. 然后onresize可以将缓冲区绘制到调整大小的窗口上。

  3. 以下是代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Window Sized Canvas</title>
        <!-- <link href="style.css" rel="stylesheet" type="text/css"/>
        Relevant style below: -->
        <style type="text/css">
            body {margin:0; padding:0;}
            canvas {display:block;}
        </style>
    </head>
    <body onresize="updateCanvas();">
        <canvas id="canvas">Your browser does not support the canvas tag</canvas>
        <script type="text/javascript">
            var canvas = document.getElementById("canvas");
            var ctx = canvas.getContext("2d");
    
            var jCanvas;
            BufferCanvas();
            updateCanvas();
    
            function updateCanvas() {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight; 
                ctx.drawImage(jCanvas,0,0,jCanvas.width,jCanvas.height,0,0,canvas.width,canvas.height);
            }
    
            function BufferCanvas() {
                jCanvas = document.createElement("canvas");
                var jc2D = jCanvas.getContext("2d");
                jCanvas.width = window.innerWidth;
                jCanvas.height = window.innerHeight;            
                var jcW = 1920; // or your max window size
                var jcH = 1080;
                var jcWH4 = (jcW*jcH)<<2;
                var jcImageData = jc2D.createImageData(jcW, jcH);
                for (i = 0; i < jcWH4; i += 4) {
                    jcImageData.data[i] = (Math.random()*255)|0;
                    jcImageData.data[i+1] = (Math.random()*255)|0;
                    jcImageData.data[i+2] = (Math.random()*255)|0;
                    jcImageData.data[i+3] = 255;
                }
                jc2D.putImageData(jcImageData, 0, 0);
            }
    
        </script>
    </body>
    </html>
    

答案 1 :(得分:0)

使用精确确定的像素值重绘画布将很慢,几乎无论如何。一个体面的大小屏幕有很多像素,它需要时间来盯着每个像素,并决定如何在JavaScript中绘制它。

可能最简单的事情就是使用CSS来上下缩放画布。这是非常快的,因为它依赖于计算机上强大的内置图像缩放功能。你不会每次都重新计算,但只要不重要,它就会很快。 Here's an implementation of this。画布上的属性“height”和“width”会影响渲染区域的大小(以像素为单位),而 style 属性“height”和“width”会影响画布占用的区域而不会修改你必须用的像素数。

详细说明:如果在不重绘任何内容的情况下增加画布的基于属性的大小,您会注意到前一个图像将保持不变;所有发生的事情是你在画布上添加了一些空白区域。但是,如果你只改变了样式,画布将变成你告诉它变成的大小,但它看起来可能看起来有颗粒感,即使画布上的所有内容理论上都可以达到那么大的高分辨率。

这会在您正在操作的图像中创建一些奇怪的工件,但这并不是简单的方法。你可以做的一件事是默认情况下,只要画布的大小发生变化就会使用CSS,但是在调整大小之后,重新绘制一个新的更高res模式。如果你决定走这条路并需要任何帮助,请告诉我。