HTML5画布100%宽度视口高度?


151

我正在尝试创建一个画布元素,该元素占用视口宽度和高度的100%。

您可以在我的示例中看到这种情况的发生,但是它正在Chrome和FireFox中添加滚动条。如何防止多余的滚动条,仅将窗口的宽度和高度设置为画布的大小?



让我想起了一个相当有趣的Fonejacker喜剧素描:youtu.be/6oj_oLMD688?t=22s
Francis Booth,

Answers:


257

为了使画布始终保持全屏宽度和高度,这意味着即使调整了浏览器的大小,也需要在将画布调整为window.innerHeight和window.innerWidth的函数中运行绘制循环。

示例:http//jsfiddle.net/jaredwilli/qFuDr/

的HTML

<canvas id="canvas"></canvas>

的JavaScript

(function() {
    var canvas = document.getElementById('canvas'),
            context = canvas.getContext('2d');

    // resize the canvas to fill browser window dynamically
    window.addEventListener('resize', resizeCanvas, false);

    function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;

            /**
             * Your drawings need to be inside this function otherwise they will be reset when 
             * you resize the browser window and the canvas goes will be cleared.
             */
            drawStuff(); 
    }
    resizeCanvas();

    function drawStuff() {
            // do your drawing stuff here
    }
})();

的CSS

* { margin:0; padding:0; } /* to remove the top and left whitespace */

html, body { width:100%; height:100%; } /* just to be sure these are full screen*/

canvas { display:block; } /* To remove the scrollbars */

这样便可以正确地使画布达到浏览器的整个宽度和高度。您只需要在drawStuff()函数中将所有用于绘制的代码放到画布上即可。


2
为什么需要去除填充并将宽度,高度设置为100%?
科斯

3
我认为这主要是为了覆盖浏览器默认的用户样式表。如果您使用某种规范化或重置的CSS文件,则无需这样做,因为这已经得到了照顾。
jaredwilli 2013年

2
如果您期望大量调整大小;例如,在纵向/横向设备上,您需要debounce调整大小,否则将使浏览器泛滥。
dooburt 2014年

24
display: block:这不仅会删除滚动条,还会从文档正文的高度中删除2px,这些像素通常添加在块内的文本行下。因此+1
Neptilo

2
加上一个没有jQuery的
费利克斯·加侬-格尼尔

26

您可以尝试视口单位(CSS3):

canvas { 
  height: 100vh; 
  width: 100vw; 
  display: block;
}

5
添加display: block;并完成工作。
superlukas 2014年

18
我尝试了一下,发现在Chrome和Firefox中,画布仅显示了拉伸到整个视口的图像。甚至新绘制的元素也会被拉伸。
维维安河

8
@Daniel是对的-这个答案是错误的。它不会设置canvas上下文的内部尺寸,而是设置DOM元素的尺寸。有关差异,请参见我对相关问题的回答
Dan Dascalescu 2015年

19
此方法不起作用,它会拉伸文本。不幸的
i336_

16

我将回答一个更通用的问题,即如何在调整窗口大小时动态调整画布的大小。可接受的答案适当地处理了宽度和高度都假定为100%的情况,这是所要求的,但同时也会改变画布的纵横比。许多用户会希望在调整窗口大小的同时调整画布的大小,但同时保持宽高比不变。这不是确切的问题,但它“适合”,只是将问题放到了更一般的背景下。

窗口将具有某些纵横比(宽度/高度),画布对象也将具有纵横比。您要如何将这两个长宽比相互关联是一件事,您必须弄清楚,这个问题没有“一刀切”的答案-我将介绍一些您可能会遇到的常见情况想。

您必须清楚的最重要的事情是:html canvas对象具有width属性和height属性;然后,同一对象的css也具有width和height属性。这两个宽度和高度是不同的,两者都可用于不同的事物。

更改width和height属性是一种始终可以更改画布大小的方法,但是随后您必须重新绘制所有内容,这将花费时间并且并不总是必要的,因为您可以完成一些大小更改通过css属性,在这种情况下,您无需重画画布。

我看到4种情况,您可能希望在调整窗口大小时发生什么(所有情况都从全屏画布开始)

1:您希望宽度保持100%,并且希望宽高比保持原样。在这种情况下,您不需要重新绘制画布;您甚至不需要窗口调整大小处理程序。所有你需要的是

$(ctx.canvas).css("width", "100%");

ctx是您的画布上下文。小提琴:resizeByWidth

2:您希望宽度和高度都保持100%,并且希望宽高比的变化具有拉伸图像的效果。现在,您仍然不需要重新绘制画布,但是需要一个窗口调整大小处理程序。在处理程序中,您可以

$(ctx.canvas).css("height", window.innerHeight);

小提琴:messWithAspectratio

3:您希望宽度和高度都保持100%,但是改变宽高比的答案与拉伸图像有所不同。然后,您需要重画,并按照接受的答案中概述的方式进行。

小提琴:重画

4:您希望宽度和高度在页面加载时为100%,但此后保持不变(对窗口调整大小无反应。

小提琴:固定

除设置模式的第63行外,所有小提琴都具有相同的代码。您还可以复制小提琴代码以在本地计算机上运行,​​在这种情况下,可以通过querystring参数选择模式,如?mode = redraw


1
fyi: $(ctx.canvas).css("width", "100%");相当于$(canvas).css("width", "100%"); (上下文的画布只是画布)
Brad Kent

@BradKent调用一个完成您要完成的“画布事情”的辅助函数时,可以作为参数1)传递画布对象,2)传递画布上下文,3)两者都可以。我不喜欢3),而且ctx.canvas比3)短很多canvas.getContext('2d')-这就是为什么我喜欢2)。因此,没有名为canvas的变量,但是有ctx.canvas。那就是ctx.canvas的来源。
mathheadinclouds

9

http://jsfiddle.net/mqFdk/10/

<!DOCTYPE html>
<html>
<head>
    <title>aj</title>
</head>
<body>

    <canvas id="c"></canvas>

</body>
</html>

使用CSS

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }

可以,但是我的画布没有定义宽度和高度。画布的宽度和高度必须在我认为的元素上定义。
aherrick 2010年

@aherrick:不,您不必在canvas元素上设置明确的宽度/高度即可使其正常工作。此代码应该可以正常工作。
乔恩·亚当斯

18
实际上,画布元素确实需要显式的宽度/高度设置。没有它,它们将默认使用一些浏览器预设的尺寸(在chrome中,我认为是300x150px)。画布上的所有图形都将以此尺寸进行解释,然后缩放为视口尺寸的100%。尝试在画布上绘制任何东西,以了解我的意思-它会变形。
马克·卡恩

如果您要使画布的宽度和高度为100%,那么这根本不重要。您无论如何
都要

1
canvas元素的固有尺寸等于坐标空间的大小,其数字以CSS像素表示。但是,可以通过样式表任意设置元素的大小。在渲染期间,将缩放图像以适合此布局大小。
jaredwilli 2012年

8

我也想找到这个问题的答案,但是被接受的答案对我来说是个难题。显然,使用window.innerWidth是不可移植的。它确实可以在某些浏览器中运行,但是我注意到Firefox不喜欢它。

格雷格·塔瓦雷斯(Gregg Tavares)在这里发布了一个很好的资源,可以直接解决此问题:http : //webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (请参阅反模式3和4)。

使用canvas.clientWidth代替window.innerWidth似乎很好。

这是Gregg建议的渲染循环:

function resize() {
  var width = gl.canvas.clientWidth;
  var height = gl.canvas.clientHeight;
  if (gl.canvas.width != width ||
      gl.canvas.height != height) {
     gl.canvas.width = width;
     gl.canvas.height = height;
     return true;
  }
  return false;
}

var needToRender = true;  // draw at least once
function checkRender() {
   if (resize() || needToRender) {
     needToRender = false;
     drawStuff();
   }
   requestAnimationFrame(checkRender);
}
checkRender();

2

(扩大动静能量的答案)

设置画布样式以填充主体。在渲染到画布时,请考虑其大小。

http://jsfiddle.net/mqFdk/356/

<!DOCTYPE html>
<html>
<head>
    <title>aj</title>
</head>
<body>

    <canvas id="c"></canvas>

</body>
</html>

CSS:

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }

Javascript:

function redraw() {
    var cc = c.getContext("2d");
    c.width = c.clientWidth;
    c.height = c.clientHeight;
    cc.scale(c.width, c.height);

    // Draw a circle filling the canvas.
    cc.beginPath();
    cc.arc(0.5, 0.5, .5, 0, 2*Math.PI);
    cc.fill();
}

// update on any window size change.
window.addEventListener("resize", redraw);

// first draw
redraw();

1

对于手机,最好使用它

canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;

因为更改方向后显示不正确。将方向更改为纵向时,“视口”会增加。请参见完整 示例

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.