如何自动缩放HTML5 <canvas>元素以适应页面?

例如,我可以得到一个<div>通过设置高度和宽度属性为100%缩放,但一个<canvas>不会缩放,会吗?


当前回答

如果你的div完全填满了网页,那么你可以填充这个div,这样就有一个画布来填充这个div。

你可能会发现这很有趣,因为你可能需要使用css来使用百分比,但是,这取决于你使用的浏览器,以及它在多大程度上符合规范: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element

画布的内在尺寸 元素的大小相等 用数字来坐标空间 用CSS像素解释。然而, 元素的大小可以任意设置 通过样式表。在呈现期间, 图像按比例缩放以适应此布局 大小。

您可能需要获取div的offsetWidth和height,或者获取窗口的高度/宽度并将其设置为像素值。

其他回答

2022的答案

在2022年,检查元素是否调整大小的推荐方法是使用ResizeObserver

const observer = new ResizeObserver(myResizeTheCanvasFn);
observer.observe(someCanvasElement);

它比窗户好。addEventListener('resize', myResizeTheCanvasFn)或onresize = myResizeTheCanvasFn,因为它处理画布调整大小的每一种情况,即使它与窗口调整大小无关。

同样,使用window也没有意义。innerWidth window.innerHeight。你想要画布本身的大小,而不是窗口的大小。这样,无论你把画布放在哪里,你都会得到正确的大小,而不必重写你的尺寸代码。

至于用画布填满窗户

html, body {
  height: 100%;
}
canvas {
  width: 100%;
  height: 100%;
  display: block;   /* this is IMPORTANT! */
}

你需要display: block的原因是因为默认情况下画布是内联的,这意味着它在结尾包含额外的空间。没有显示:块你将得到一个滚动条。许多人通过在文档正文中添加overflow: hidden来修复滚动条问题,但这只是隐藏了画布的CSS设置不正确的事实。最好是修复bug(将canvas设置为display: block而不是使用overflow: hidden隐藏bug)

完整的示例

const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); const observer = new ResizeObserver((entries) => { canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; }); observer.observe(canvas) // not import but draw something just to showcase const hsla = (h, s, l, a) => `hsla(${h * 360}, ${s * 100}%, ${l * 100}%, ${a})`; function render(time) { const {width, height} = canvas; ctx.clearRect(0, 0, width, height); ctx.save(); ctx.translate(width / 2, height / 2); ctx.rotate(time * 0.0001); const range = Math.max(width, height) * 0.8; const size = 64 + Math.sin(time * 0.001) * 50; for (let i = 0; i < range; i += size) { ctx.fillStyle = hsla(i / range * 0.3 + time * 0.0001, 1, 0.5, 1); ctx.fillRect( i, -range, size, range * 2); ctx.fillRect(-i, -range, size, range * 2); } ctx.restore(); requestAnimationFrame(render) } requestAnimationFrame(render) html, body { height: 100%; margin: 0; } canvas { width: 100%; height: 100%; display: block; } <canvas></canvas>

注意:还有其他与调整画布大小相关的问题。特别是如果你想处理不同的devicePixelRatio设置。请参阅本文了解更多信息。

如果你的div完全填满了网页,那么你可以填充这个div,这样就有一个画布来填充这个div。

你可能会发现这很有趣,因为你可能需要使用css来使用百分比,但是,这取决于你使用的浏览器,以及它在多大程度上符合规范: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element

画布的内在尺寸 元素的大小相等 用数字来坐标空间 用CSS像素解释。然而, 元素的大小可以任意设置 通过样式表。在呈现期间, 图像按比例缩放以适应此布局 大小。

您可能需要获取div的offsetWidth和height,或者获取窗口的高度/宽度并将其设置为像素值。

下面的解决方案对我来说效果最好。因为我对编码相对陌生,所以我喜欢用视觉来确认某些东西是否按照我期望的方式工作。我在以下地点找到了它: http://htmlcheats.com/html/resize-the-html5-canvas-dyamically/

代码如下:

(function() { var // Obtain a reference to the canvas element using its id. htmlCanvas = document.getElementById('c'), // Obtain a graphics context on the canvas element for drawing. context = htmlCanvas.getContext('2d'); // Start listening to resize events and draw canvas. initialize(); function initialize() { // Register an event listener to call the resizeCanvas() function // each time the window is resized. window.addEventListener('resize', resizeCanvas, false); // Draw canvas border for the first time. resizeCanvas(); } // Display custom canvas. In this case it's a blue, 5 pixel // border that resizes along with the browser window. function redraw() { context.strokeStyle = 'blue'; context.lineWidth = '5'; context.strokeRect(0, 0, window.innerWidth, window.innerHeight); } // Runs each time the DOM window resize event fires. // Resets the canvas dimensions to match window, // then draws the new borders accordingly. function resizeCanvas() { htmlCanvas.width = window.innerWidth; htmlCanvas.height = window.innerHeight; redraw(); } })(); html, body { width: 100%; height: 100%; margin: 0px; border: 0; overflow: hidden; /* Disable scrollbars */ display: block; /* No floating content on sides */ } <canvas id='c' style='position:absolute; left:0px; top:0px;'></canvas>

蓝色边框显示了调整画布的边缘,并且总是沿着窗口的边缘,在所有4个面都可见,这不是上述其他一些答案的情况。希望能有所帮助。

这对我很管用。 伪代码:

// screen width and height
scr = {w:document.documentElement.clientWidth,h:document.documentElement.clientHeight}
canvas.width = scr.w
canvas.height = scr.h

另外,就像devyn说的,您可以替换“document.documentElement”。宽度和高度均为“inner”的客户端:

**document.documentElement.client**Width
**inner**Width
**document.documentElement.client**Height
**inner**Height

它仍然有效。

function resize() {

    var canvas = document.getElementById('game');
    var canvasRatio = canvas.height / canvas.width;
    var windowRatio = window.innerHeight / window.innerWidth;
    var width;
    var height;

    if (windowRatio < canvasRatio) {
        height = window.innerHeight;
        width = height / canvasRatio;
    } else {
        width = window.innerWidth;
        height = width * canvasRatio;
    }

    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';
};

window.addEventListener('resize', resize, false);