HTML5 Canvas 100% Chiều rộng chiều rộng của Viewport?


151

Tôi đang cố gắng tạo một phần tử canvas chiếm 100% chiều rộng và chiều cao của khung nhìn.

Bạn có thể thấy trong ví dụ của tôi ở đây đang xảy ra, tuy nhiên nó đang thêm các thanh cuộn trong cả Chrome và FireFox. Làm cách nào tôi có thể ngăn các thanh cuộn thêm và chỉ cung cấp chính xác chiều rộng và chiều cao của cửa sổ là kích thước của khung vẽ?



Nhắc nhở tôi về một bản phác thảo hài Fonejacker khá thú vị: youtu.be/6oj_oLMD688?t=22s
Gian hàng của Francis

Câu trả lời:


258

Để luôn luôn làm cho chiều rộng và chiều cao của màn hình đầy đủ, có nghĩa là ngay cả khi trình duyệt được thay đổi kích thước, bạn cần chạy vòng vẽ của mình trong một chức năng thay đổi kích thước của khung vẽ sang window.innerHeight và window.innerWidth.

Ví dụ: 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 */

Đó là cách bạn làm cho khung vẽ đầy đủ chiều rộng và chiều cao của trình duyệt. Bạn chỉ cần đặt tất cả mã để vẽ vào khung vẽ trong hàm drawStuff ().


2
Tại sao cần phải loại bỏ phần đệm và đặt chiều rộng, chiều cao thành 100%?
Kos

3
Tôi tin rằng nó chủ yếu để ghi đè lên biểu định kiểu người dùng mà trình duyệt đã mặc định. Nếu bạn đang sử dụng một số loại tệp css bình thường hóa hoặc đặt lại, điều này không cần thiết vì điều đó sẽ được xử lý.
jaredwilli

2
Nếu bạn mong đợi khá nhiều thay đổi kích thước; chẳng hạn trên thiết bị dọc / ngang, bạn muốn debouncethay đổi kích thước nếu không bạn sẽ làm ngập trình duyệt.
dooburt

24
display: block: Điều này không chỉ xóa thanh cuộn mà còn xóa 2px khỏi chiều cao của thân tài liệu, thường được thêm vào dưới các dòng văn bản bên trong một khối. Vì vậy, +1 cho điều đó
Neptilo

2
cộng với một không có jQuery
Félix Gagnon-Grenier

26

Bạn có thể thử các đơn vị khung nhìn (CSS3):

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

5
Thêm display: block;và nó làm công việc.
superlukas

18
Tôi đã thử điều này và thấy rằng trong Chrome và Firefox, khung vẽ chỉ hiển thị hình ảnh được kéo dài đến chế độ xem đầy đủ. Ngay cả các yếu tố mới được vẽ cũng được kéo dài.
Sông Vivian

8
@Daniel đúng - câu trả lời này sai . Nó sẽ không đặt kích thước bên trong của bối cảnh canvas, mà là kích thước của phần tử DOM. Đối với sự khác biệt, xem câu trả lời của tôi cho một câu hỏi liên quan .
Dan Dascalescu

19
Phương pháp này không hoạt động, nó kéo dài văn bản. Bạn không may phải sử dụng JS.
i336_

16

Tôi sẽ trả lời câu hỏi chung hơn về làm thế nào để có một khung vẽ tự động thích ứng kích thước khi thay đổi kích thước cửa sổ. Câu trả lời được chấp nhận xử lý thích hợp trường hợp cả chiều rộng và chiều cao được cho là 100%, đó là những gì được yêu cầu, nhưng cũng sẽ thay đổi tỷ lệ khung hình của khung vẽ. Nhiều người dùng sẽ muốn thay đổi kích thước khung hình trên thay đổi kích thước cửa sổ, nhưng vẫn giữ nguyên tỷ lệ khung hình. Đây không phải là câu hỏi chính xác, nhưng nó "phù hợp", chỉ đặt câu hỏi vào một bối cảnh chung hơn một chút.

Cửa sổ sẽ có một số tỷ lệ khung hình (chiều rộng / chiều cao) và đối tượng canvas cũng vậy. Bạn muốn hai tỷ lệ khung hình này liên quan với nhau như thế nào là một điều bạn sẽ phải rõ ràng, không có câu trả lời "một kích thước phù hợp cho tất cả" cho câu hỏi đó - Tôi sẽ xem xét một số trường hợp phổ biến về những gì bạn có thể muốn

Điều quan trọng nhất bạn phải rõ ràng: đối tượng canvas html có thuộc tính width và thuộc tính height; và sau đó, css của cùng một đối tượng cũng có thuộc tính chiều rộng và chiều cao. Hai chiều rộng và chiều cao đó là khác nhau, cả hai đều hữu ích cho những thứ khác nhau.

Thay đổi các thuộc tính chiều rộng và chiều cao là một phương pháp mà bạn luôn có thể thay đổi kích thước của khung vẽ, nhưng sau đó bạn sẽ phải sơn lại mọi thứ, sẽ mất thời gian và không phải lúc nào cũng cần thiết, bởi vì một số lượng thay đổi kích thước bạn có thể thực hiện thông qua các thuộc tính css, trong trường hợp đó bạn không vẽ lại khung vẽ.

Tôi thấy 4 trường hợp về những gì bạn có thể muốn xảy ra trên thay đổi kích thước cửa sổ (tất cả bắt đầu bằng một khung hình toàn màn hình)

1: bạn muốn chiều rộng duy trì 100% và bạn muốn tỷ lệ khung hình được giữ nguyên. Trong trường hợp đó, bạn không cần vẽ lại khung vẽ; bạn thậm chí không cần một trình xử lý thay đổi kích thước cửa sổ. Tất cả bạn cần là

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

trong đó ctx là bối cảnh vải của bạn. fiddle: thay đổi kích thướcByWidth

2: bạn muốn cả chiều rộng và chiều cao đều ở mức 100% và bạn muốn thay đổi kết quả về tỷ lệ khung hình để có hiệu ứng của hình ảnh kéo dài. Bây giờ, bạn vẫn không cần vẽ lại khung vẽ, nhưng bạn cần một trình xử lý thay đổi kích thước cửa sổ. Trong xử lý, bạn làm

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

fiddle: messWithAspectratio

3: bạn muốn cả chiều rộng và chiều cao đều giữ nguyên 100%, nhưng câu trả lời cho sự thay đổi tỷ lệ khung hình là một cái gì đó khác với việc kéo dài hình ảnh. Sau đó, bạn cần vẽ lại, và làm theo cách được nêu trong câu trả lời được chấp nhận.

fiddle: vẽ lại

4: bạn muốn chiều rộng và chiều cao là 100% khi tải trang, nhưng không đổi sau đó (không có phản ứng thay đổi kích thước cửa sổ.

fiddle: đã sửa

Tất cả các câu đố có mã giống hệt nhau, ngoại trừ dòng 63 nơi chế độ được đặt. Bạn cũng có thể sao chép mã fiddle để chạy trên máy cục bộ của mình, trong trường hợp đó bạn có thể chọn chế độ thông qua đối số chuỗi truy vấn, như? Mode = vẽ lại


1
fyi: $(ctx.canvas).css("width", "100%");tương đương với $(canvas).css("width", "100%"); (khung vẽ của bối cảnh chỉ là khung vẽ)
Brad Kent

@BradKent khi bạn gọi một hàm trợ giúp thực hiện "canvas-thing" mà bạn muốn thực hiện, bạn có thể, như (các) đối số 1) truyền đối tượng canvas, 2) vượt qua bối cảnh canvas, 3) cả hai. Tôi không thích 3), và ctx.canvasngắn hơn rất nhiều canvas.getContext('2d')- đó là lý do tại sao tôi làm 2). Do đó, không có biến được gọi là canvas, nhưng có ctx.canvas. Đó là nơi ctx.canvas đến từ.
mathheadinclouds

9

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

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

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

</body>
</html>

với CSS

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

Điều này hoạt động, nhưng nó rời khỏi khung vẽ của tôi mà không có chiều rộng và chiều cao xác định. Chiều rộng và chiều cao của khung vẽ phải được xác định trên thành phần tôi tin.
aherrick

@aherrick: Không, bạn không cần phải đặt chiều rộng / chiều cao rõ ràng trên phần tử canvas để nó hoạt động. Mã này sẽ hoạt động tốt.
Jon Adams

18
Trên thực tế có, các phần tử canvas cần một bộ chiều rộng / chiều cao rõ ràng. Không có nó, họ mặc định với một số trình duyệt được cài đặt sẵn (bằng chrome, tôi nghĩ đó là kích thước 300x150px). Tất cả các bản vẽ vào khung vẽ được diễn giải ở kích thước này và sau đó được chia tỷ lệ thành 100% kích thước khung nhìn. Hãy thử vẽ bất cứ thứ gì trong khung vẽ của bạn để xem ý tôi là gì - nó sẽ bị biến dạng.
Mark Kahn

nếu bạn đang cố gắng tạo khung vẽ 100% chiều rộng và chiều cao thì điều đó thậm chí không quan trọng. bạn chỉ cần thay đổi kích thước dù sao đi nữa
jaredwilli

1
Kích thước nội tại của phần tử canvas bằng kích thước của không gian tọa độ, với các số được diễn giải bằng pixel CSS. Tuy nhiên, phần tử có thể được kích thước tùy ý bằng một biểu định kiểu. Trong quá trình kết xuất, hình ảnh được thu nhỏ để phù hợp với kích thước bố cục này.
jaredwilli

8

Tôi đang tìm kiếm câu trả lời cho câu hỏi này, nhưng câu trả lời được chấp nhận đã phá vỡ cho tôi. Rõ ràng là sử dụng window.innerWidth không thể di động. Nó hoạt động trong một số trình duyệt, nhưng tôi nhận thấy Firefox không thích nó.

Gregg Tavares đã đăng một tài nguyên tuyệt vời ở đây để giải quyết vấn đề này trực tiếp: http://webglfundamentals.org/webgl/lessons/webgl-anti-potypes.html (Xem phần chống mẫu số 3 và 4).

Sử dụng canvas.clientWidth thay vì window.innerWidth dường như hoạt động độc đáo.

Đây là vòng lặp kết xuất được đề xuất của 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

(Mở rộng theo câu trả lời của))

Phong cách vải để lấp đầy cơ thể. Khi kết xuất vào khung vẽ, hãy tính đến kích thước của nó.

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

Đối với điện thoại di động, tốt hơn là sử dụng nó

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

bởi vì nó sẽ hiển thị không chính xác sau khi thay đổi hướng. Chế độ xem trực quan sẽ được tăng lên khi thay đổi hướng thành chân dung. Xem ví dụ đầy đủ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.