Płótno HTML5 100% szerokość Wysokość rzutni?

151

Próbuję stworzyć element płótna, który zajmuje 100% szerokości i wysokości widoku.

Możesz zobaczyć w moim przykładzie tutaj, że ma miejsce, jednak dodaje paski przewijania zarówno w Chrome, jak i FireFox. Jak mogę zapobiec dodatkowym paskom przewijania i po prostu określić dokładnie szerokość i wysokość okna, aby odpowiadały rozmiarowi płótna?

aherrick
źródło
1
Zobacz też: stackoverflow.com/questions/4037212
hippietrail
Przypomina mi dość zabawny szkic komediowy Fonejackera
Francis Booth

Odpowiedzi:

258

Aby płótno było zawsze na całej szerokości i wysokości ekranu, co oznacza, że ​​nawet po zmianie rozmiaru przeglądarki, musisz uruchomić pętlę rysowania w funkcji, która zmienia rozmiar obszaru roboczego na window.innerHeight i window.innerWidth.

Przykład: 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 */

W ten sposób poprawnie wykonujesz płótno na pełną szerokość i wysokość przeglądarki. Wystarczy umieścić cały kod do rysowania na płótnie w funkcji drawStuff ().

jaredwilli
źródło
2
Dlaczego konieczne jest usunięcie obicia i ustawienie szerokości, wysokości na 100%?
Kos
3
Uważam, że służy to głównie do zastępowania arkusza stylów użytkownika, dla którego przeglądarka ma ustawienia domyślne. Jeśli używasz jakiegoś normalizującego lub resetowanego pliku css, nie jest to konieczne, ponieważ zostanie to już rozwiązane.
jaredwilli
2
Jeśli spodziewasz się dużo zmiany rozmiaru; na przykład na urządzeniu pionowym / poziomym, chciałbyś debouncezmienić rozmiar, w przeciwnym razie zalejisz przeglądarkę.
dooburt
24
display: block: To nie tylko usuwa paski przewijania, ale także usuwa 2 piksele z wysokości treści dokumentu, które zwykle są dodawane pod liniami tekstu wewnątrz bloku. Więc +1 za to
Neptilo,
2
plus jeden za brak jQuery
Félix Gagnon-Grenier
26

Możesz wypróbować jednostki widoku (CSS3):

canvas { 
  height: 100vh; 
  width: 100vw; 
  display: block;
}
Vitalii Fedorenko
źródło
5
Dodaj display: block;i spełnia swoje zadanie.
superlukas
18
Wypróbowałem to i stwierdziłem, że w przeglądarce Chrome i Firefox płótno po prostu pokazuje obraz rozciągnięty do pełnego obszaru roboczego. Nawet nowo narysowane elementy są również rozciągane.
Vivian River
8
@Daniel ma rację - ta odpowiedź jest zła . Nie ustawi wewnętrznego wymiaru kontekstu kanwy, ale raczej wymiary elementu DOM. Aby zobaczyć różnicę, zobacz moją odpowiedź na powiązane pytanie .
Dan Dascalescu
19
Ta metoda nie działa, rozciąga tekst. Niestety musisz użyć JS.
i336_
16

Odpowiem na bardziej ogólne pytanie, jak dynamicznie dostosowywać rozmiar płótna po zmianie rozmiaru okna. Zaakceptowana odpowiedź odpowiednio obsługuje przypadek, w którym szerokość i wysokość mają wynosić 100%, o co pytano, ale co również zmieni proporcje płótna. Wielu użytkowników będzie chciało zmienić rozmiar płótna przy zmianie rozmiaru okna, ale zachowując współczynnik proporcji nietknięty. Nie jest to dokładne pytanie, ale „pasuje”, po prostu umieszczając pytanie w nieco bardziej ogólnym kontekście.

Okno będzie miało pewne proporcje (szerokość / wysokość), podobnie jak obiekt płótna. To, w jaki sposób chcesz, aby te dwa współczynniki kształtu odnosiły się do siebie, to jedna rzecz, którą musisz wyjaśnić, nie ma jednej odpowiedzi na to pytanie - omówię kilka typowych przypadków chcieć.

Najważniejsza rzecz, o której musisz wiedzieć: obiekt html canvas ma atrybut szerokości i atrybut wysokości; a następnie css tego samego obiektu ma również atrybut szerokości i wysokości. Te dwie szerokości i wysokości są różne, obie są przydatne do różnych rzeczy.

Zmiana atrybutów szerokości i wysokości to jedna z metod, dzięki której zawsze możesz zmienić rozmiar swojego płótna, ale wtedy będziesz musiał przemalować wszystko, co zajmie trochę czasu i nie zawsze jest konieczne, ponieważ możesz dokonać pewnej zmiany rozmiaru poprzez atrybuty css, w takim przypadku nie przerysujesz płótna.

Widzę 4 przypadki tego, co może się wydarzyć przy zmianie rozmiaru okna (wszystkie zaczynają się od płótna pełnoekranowego)

1: chcesz, aby szerokość pozostała 100% i chcesz, aby współczynnik proporcji pozostał taki, jaki był. W takim przypadku nie musisz przerysowywać płótna; nie potrzebujesz nawet obsługi zmiany rozmiaru okna. Wszystko czego potrzebujesz to

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

gdzie ctx to kontekst twojego płótna. skrzypce: resizeByWidth

2: chcesz, aby szerokość i wysokość pozostały na 100%, i chcesz, aby wynikowa zmiana współczynnika proporcji miała efekt rozciągniętego obrazu. Teraz nadal nie musisz przerysowywać płótna, ale potrzebujesz programu obsługi zmiany rozmiaru okna. W programie obsługi tak

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

skrzypce: messWithAspectratio

3: chcesz, aby szerokość i wysokość pozostały w 100%, ale odpowiedź na zmianę współczynnika kształtu jest czymś innym niż rozciągnięcie obrazu. Następnie musisz przerysować i zrób to w sposób opisany w zaakceptowanej odpowiedzi.

skrzypce: przerysuj

4: chcesz, aby szerokość i wysokość były równe 100% podczas ładowania strony, ale później pozostań na stałym poziomie (brak reakcji na zmianę rozmiaru okna.

skrzypce: naprawiono

Wszystkie skrzypce mają identyczny kod, z wyjątkiem linii 63, w której ustawiono tryb. Możesz również skopiować kod skrzypcowy, aby uruchomić go na komputerze lokalnym, w którym to przypadku możesz wybrać tryb za pomocą argumentu querystring, jak? Mode = redraw

mathheadinclouds
źródło
1
fyi: $(ctx.canvas).css("width", "100%");jest odpowiednikiem $(canvas).css("width", "100%"); (płótno kontekstu to tylko płótno)
Brad Kent
@BradKent kiedy wywołujesz funkcję pomocniczą, która wykonuje "rzeczy na płótnie", które chcesz wykonać, możesz albo jako argument (i) 1) przekazać obiekt kanwy, 2) przekazać kontekst kanwy, 3) oba. Nie lubię 3) i ctx.canvasjest dużo krótszy niżcanvas.getContext('2d') - dlatego robię 2). Dlatego nie ma zmiennej o nazwie canvas, ale istnieje ctx.canvas. Stąd pochodzi ctx.canvas.
mathheadinclouds
9

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

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

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

</body>
</html>

z CSS

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }
brak biegunowości
źródło
To działa, ale pozostawia moje płótno bez określonej szerokości i wysokości. Uważam, że szerokość i wysokość płótna muszą być zdefiniowane w elemencie.
aherrick
@aherrick: Nie, nie musisz mieć jawnej szerokości / wysokości ustawionej w elemencie canvas, aby działał. Ten kod powinien działać dobrze.
Jon Adams,
18
Właściwie tak, elementy płótna wymagają wyraźnego ustawienia szerokości / wysokości. Bez tego domyślnie mają wstępnie ustawiony rozmiar przeglądarki (w chrome, myślę, że to 300x150px). Cały rysunek na płótnie jest interpretowany w tym rozmiarze, a następnie skalowany do 100% rozmiaru rzutni. Spróbuj narysować cokolwiek na swoim płótnie, aby zobaczyć, co mam na myśli - zostanie zniekształcone.
Mark Kahn,
jeśli próbujesz zrobić płótno w 100% szerokości i wysokości, to w ogóle nie ma to znaczenia. i tak po prostu zmieniasz jego rozmiar
jaredwilli
1
Wewnętrzne wymiary elementu canvas są równe rozmiarowi przestrzeni współrzędnych, a liczby są interpretowane w pikselach CSS. Jednak rozmiar elementu można dowolnie zmieniać za pomocą arkusza stylów. Podczas renderowania obraz jest skalowany w celu dopasowania do tego rozmiaru układu.
jaredwilli,
8

Szukałem odpowiedzi na to pytanie, ale zaakceptowana odpowiedź była dla mnie załamująca. Najwyraźniej użycie window.innerWidth nie jest przenośne. Działa w niektórych przeglądarkach, ale zauważyłem, że Firefoxowi się to nie spodobało.

Gregg Tavares zamieścił tutaj świetne źródło, które bezpośrednio rozwiązuje ten problem: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (patrz przeciw wzorowi # 3 i 4).

Wydaje się, że użycie canvas.clientWidth zamiast window.innerWidth działa dobrze.

Oto sugerowana pętla renderowania Gregga:

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();
David
źródło
2

(Rozszerzanie odpowiedzi 動靜 能量)

Stylizuj płótno, aby wypełniło ciało. Podczas renderowania na płótnie należy wziąć pod uwagę jego rozmiar.

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();
Vincent Scheib
źródło
1

W przypadku telefonów komórkowych lepiej go używać

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

ponieważ po zmianie orientacji będzie wyświetlany nieprawidłowo. „Rzutnia” zostanie zwiększona po zmianie orientacji na pionową. Zobacz pełny przykład

dzanis
źródło