HTML5 Canvas 100% Ширина Высота области просмотра?

151

Я пытаюсь создать элемент canvas, который занимает 100% ширины и высоты области просмотра.

Вы можете видеть в моем примере, который здесь происходит, однако он добавляет полосы прокрутки как в Chrome, так и в FireFox. Как я могу запретить лишние полосы прокрутки и просто точно указать ширину и высоту окна в соответствии с размером холста?

aherrick
источник
1
См. Также: stackoverflow.com/questions/4037212
hippietrail
Напоминает мне довольно забавный комедийный набросок Fonejacker: youtu.be/6oj_oLMD688?t=22s
Фрэнсис Бут

Ответы:

258

Чтобы холст всегда был на всю ширину и высоту экрана, т. Е. Даже при изменении размера браузера, вам нужно запустить цикл рисования внутри функции, которая изменяет размер холста до 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 ().

jaredwilli
источник
2
Почему необходимо убрать отступы и установить ширину, высоту на 100%?
Кос
3
Я полагаю, что это главным образом для переопределения пользовательской таблицы стилей, для которой браузер имеет значения по умолчанию. Если вы используете какой-либо файл нормализации или сброса CSS, это не обязательно, так как об этом уже позаботятся.
Джаредвилли
2
Если вы ожидаете довольно большого изменения размера; на портретном / альбомном устройстве, например, вы захотите debounceизменить размер, иначе вы запустите браузер.
дообурт
24
display: block: Это не только удаляет полосы прокрутки, но и удаляет 2 пикселя от высоты тела документа, которые обычно добавляются под текстовыми строками внутри блока. Так что +1 за это
Neptilo
2
плюс один без jQuery
Феликс Ганьон-Гренье
26

Вы можете попробовать единицы просмотра (CSS3):

canvas { 
  height: 100vh; 
  width: 100vw; 
  display: block;
}
Виталий Федоренко
источник
5
Добавьте display: block;и это сделает работу.
суперлукас
18
Я попробовал это и обнаружил, что в Chrome и Firefox холст просто показывает изображение, растянутое до полного окна просмотра. Даже недавно нарисованные элементы растягиваются.
Река Вивиан
8
@ Даниил прав - этот ответ неправильный . Он не будет устанавливать внутреннее измерение контекста холста, а скорее размеры элемента DOM. Для разницы, см. Мой ответ на связанный вопрос .
Дан Даскалеску
19
Этот метод не работает, он растягивает текст. К сожалению, вы должны использовать JS.
i336_
16

Я отвечу на более общий вопрос о том, как сделать так, чтобы холст динамически изменялся в размерах при изменении размера окна. Принятый ответ соответствующим образом обрабатывает случай, когда ширина и высота должны быть равны 100%, что и требовалось, но также изменит соотношение сторон холста. Многие пользователи захотят изменить размер холста при изменении размера окна, но при этом не изменяя пропорции. Это не точный вопрос, но он «вписывается», просто помещая вопрос в чуть более общий контекст.

Окно будет иметь некоторое соотношение сторон (ширина / высота), как и объект Canvas. То, как вы хотите, чтобы эти два аспектных соотношения соотносились друг с другом, - это одна вещь, о которой вы должны уяснить: на этот вопрос не существует ответа «один размер подходит всем» - я рассмотрю несколько общих случаев того, что вы можете хотеть.

Самая важная вещь, которую вы должны прояснить: 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, в которой установлен режим. Вы также можете скопировать код скрипты для запуска на локальном компьютере, и в этом случае вы можете выбрать режим с помощью аргумента строки запроса, например? Mode = redraw

mathheadinclouds
источник
1
К вашему сведению: $(ctx.canvas).css("width", "100%");эквивалентно $(canvas).css("width", "100%"); (холст контекста просто холст)
Брэд Кент
@BradKent, когда вы вызываете вспомогательную функцию, которая выполняет «холст-вещи», которые вы хотите сделать, вы можете в качестве аргумента (ов) 1) передать объект холста, 2) передать контекст холста, 3) оба. Мне не нравится 3), и ctx.canvasон намного короче canvas.getContext('2d'), поэтому я делаю 2). Следовательно, нет переменной с именем canvas, но есть ctx.canvas. Вот откуда взялся ctx.canvas.
Математические облака
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
   }
nonopolarity
источник
Это работает, но оставляет мой холст без определенной ширины и высоты. Ширина и высота холста должны быть определены на элементе, которому я верю.
Aherrick
@aherrick: Нет, вам не нужно задавать явную ширину / высоту для элемента canvas, чтобы он работал. Этот код должен работать нормально.
Джон Адамс
18
На самом деле да, элементам canvas действительно необходим явный набор ширины / высоты. Без этого они по умолчанию настроены на какой-то предустановленный браузер (в chrome, я думаю, это 300x150px) размера. Все рисунки на холст интерпретируются с таким размером, а затем масштабируются до 100% от размера области просмотра. Попробуйте нарисовать что-нибудь на холсте, чтобы понять, что я имею в виду - оно будет искажено.
Марк Кан
если вы пытаетесь сделать холст 100% шириной и высотой, то это даже не имеет значения. в любом случае вы просто измените его размер
Джаредвилли
1
Внутренние размеры элемента canvas равны размеру координатного пространства, а числа интерпретируются в CSS-пикселях. Тем не менее, размер элемента может быть изменен произвольно с помощью таблицы стилей. Во время рендеринга изображение масштабируется для соответствия размеру макета.
Джаредвилли
8

Я тоже искал ответ на этот вопрос, но принятый ответ сломался для меня. Очевидно, использование window.innerWidth не является переносимым. Это работает в некоторых браузерах, но я заметил, что Firefox это не понравилось.

Грегг Таварес (Gregg Tavares) разместил здесь замечательный ресурс, который напрямую решает эту проблему: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (см. Anti-pattern # 's 3 и 4).

Использование canvas.clientWidth вместо window.innerWidth, кажется, работает хорошо.

Вот предложенный Греггом цикл рендеринга:

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;

потому что он будет отображаться неправильно после изменения ориентации. «Область просмотра» будет увеличена при изменении ориентации на портрет. Смотрите полный пример

dzanis
источник