如何自动缩放HTML5 <canvas>
元素以适合页面?
例如,我可以通过将<div>
和height
属性设置为100%来缩放width
,但<canvas>
无法扩展,是否会?
答案 0 :(得分:342)
我相信我找到了一个优雅的解决方案:
<强>的JavaScript 强>
/* important! for alignment, you should make things
* relative to the canvas' current width/height.
*/
function draw() {
var ctx = (a canvas context);
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
//...drawing code...
}
<强> CSS 强>
html, body {
width: 100%;
height: 100%;
margin: 0;
}
到目前为止,对我没有任何大的负面影响。
答案 1 :(得分:53)
以下解决方案最适合我。由于我对编码比较陌生,我喜欢用视觉确认某些东西按照我期望的方式工作。我在以下网站找到了它: http://htmlcheats.com/html/resize-the-html5-canvas-dyamically/
以下是代码:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>Resize HTML5 canvas dynamically | www.htmlcheats.com</title>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0px;
border: 0;
overflow: hidden; /* Disable scrollbars */
display: block; /* No floating content on sides */
}
</style>
</head>
<body>
<canvas id='c' style='position:absolute; left:0px; top:0px;'>
</canvas>
<script>
(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();
}
})();
</script>
</body>
</html>
蓝色边框显示调整大小画布的边缘,并且始终沿着窗口的边缘,在所有4个边上都可见,而上述其他一些答案则不然。希望它有所帮助。
答案 2 :(得分:20)
基本上你需要做的是将onresize事件绑定到你的身体,一旦你捕获事件你只需要使用window.innerWidth和window.innerHeight调整画布大小。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Canvas Resize</title>
<script type="text/javascript">
function resize_canvas(){
canvas = document.getElementById("canvas");
if (canvas.width < window.innerWidth)
{
canvas.width = window.innerWidth;
}
if (canvas.height < window.innerHeight)
{
canvas.height = window.innerHeight;
}
}
</script>
</head>
<body onresize="resize_canvas()">
<canvas id="canvas">Your browser doesn't support canvas</canvas>
</body>
</html>
答案 3 :(得分:18)
根据浏览器客户端的尺寸设置画布坐标空间的宽度和高度,需要在调整浏览器大小时调整大小和重绘。
一个不太复杂的解决方案是在Javascript变量中维护可绘制的维度,但是根据screen.width,screen.height维度设置画布尺寸。使用CSS来适应:
#containingDiv {
overflow: hidden;
}
#myCanvas {
position: absolute;
top: 0px;
left: 0px;
}
浏览器窗口通常不会大于屏幕本身(屏幕分辨率误报的地方除外,因为可能是非匹配的双显示器),因此背景不会显示,像素比例也会增加不一样。除非使用CSS缩放画布,否则画布像素将与屏幕分辨率成正比。
答案 4 :(得分:12)
纯CSS 方法添加到上面的@jerseyboy解决方案 适用于Firefox(在v29中测试),Chrome(在v34中测试)和Internet Explorer(在v11中测试)。
<!DOCTYPE html>
<html>
<head>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
canvas {
background-color: #ccc;
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<script>
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillRect(25,25,100,100);
ctx.clearRect(45,45,60,60);
ctx.strokeRect(50,50,50,50);
}
</script>
</body>
</html>
链接到示例:http://temporaer.net/open/so/140502_canvas-fit-to-window.html
但请小心,正如@jerseyboy在评论中指出的那样:
使用CSS重新调整画布很麻烦。至少在Chrome和 Safari,鼠标/触摸事件位置不会与1:1对应 画布像素位置,你必须转换坐标 系统
答案 5 :(得分:8)
除非您希望画布自动升级您的图像数据(这就是James Black的回答,但它看起来不太漂亮),您必须自己调整大小并重新绘制图像。 Centering a canvas
答案 6 :(得分:8)
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);
答案 7 :(得分:4)
如果您的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,或获取窗口高度/宽度并将其设置为像素值。
答案 8 :(得分:3)
如果您对保留宽高比感兴趣并且在纯CSS中这样做(给定宽高比),您可以执行以下操作。关键是padding-bottom
元素上的::content
,它会调整container
元素的大小。这是相对于其父宽度的大小,默认为100%
。此处指定的比率必须与canvas
元素上的尺寸比率相匹配。
// Javascript
var canvas = document.querySelector('canvas'),
context = canvas.getContext('2d');
context.fillStyle = '#ff0000';
context.fillRect(500, 200, 200, 200);
context.fillStyle = '#000000';
context.font = '30px serif';
context.fillText('This is some text that should not be distorted, just scaled', 10, 40);
&#13;
/*CSS*/
.container {
position: relative;
background-color: green;
}
.container::after {
content: ' ';
display: block;
padding: 0 0 50%;
}
.wrapper {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
canvas {
width: 100%;
height: 100%;
}
&#13;
<!-- HTML -->
<div class=container>
<div class=wrapper>
<canvas width=1200 height=600></canvas>
</div>
</div>
&#13;
答案 9 :(得分:2)
<强> CSS 强>
body { margin: 0; }
canvas { display: block; }
<强>的JavaScript 强>
window.addEventListener("load", function()
{
var canvas = document.createElement('canvas'); document.body.appendChild(canvas);
var context = canvas.getContext('2d');
function draw()
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(0, 0); context.lineTo(canvas.width, canvas.height);
context.moveTo(canvas.width, 0); context.lineTo(0, canvas.height);
context.stroke();
}
function resize()
{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
draw();
}
window.addEventListener("resize", resize);
resize();
});
答案 10 :(得分:1)
(function() {
// get viewport size
getViewportSize = function() {
return {
height: window.innerHeight,
width: window.innerWidth
};
};
// update canvas size
updateSizes = function() {
var viewportSize = getViewportSize();
$('#myCanvas').width(viewportSize.width).height(viewportSize.height);
$('#myCanvas').attr('width', viewportSize.width).attr('height', viewportSize.height);
};
// run on load
updateSizes();
// handle window resizing
$(window).on('resize', function() {
updateSizes();
});
}());
答案 11 :(得分:1)
这是一个很小的,完整的代码段,其中包含所有答案。按:“运行代码段”,然后按“整页”并调整窗口大小以查看实际效果:
function refresh(referenceWidth, referenceHeight, drawFunction) {
const myCanvas = document.getElementById("myCanvas");
myCanvas.width = myCanvas.clientWidth;
myCanvas.height = myCanvas.clientHeight;
const ratio = Math.min(
myCanvas.width / referenceWidth,
myCanvas.height / referenceHeight
);
const ctx = myCanvas.getContext("2d");
ctx.scale(ratio, ratio);
drawFunction(ctx, ratio);
window.requestAnimationFrame(() => {
refresh(referenceWidth, referenceHeight, drawFunction);
});
}
//100, 100 is the "reference" size. Choose whatever you want.
refresh(100, 100, (ctx, ratio) => {
//Custom drawing code! Draw whatever you want here.
const referenceLineWidth = 1;
ctx.lineWidth = referenceLineWidth / ratio;
ctx.beginPath();
ctx.strokeStyle = "blue";
ctx.arc(50, 50, 49, 0, 2 * Math.PI);
ctx.stroke();
});
div {
width: 90vw;
height: 90vh;
}
canvas {
width: 100%;
height: 100%;
object-fit: contain;
}
<div>
<canvas id="myCanvas"></canvas>
</div>
此代码段使用canvas.clientWidth和canvas.clientHeight而不是window.innerWidth和window.innerHeight来使代码段在复杂的布局中正确运行。但是,如果将其放在使用全窗口的div中,它也适用于全窗口。这样更灵活。
该片段使用新颖的window.requestAnimationFrame在每一帧重复调整画布的大小。如果您不能使用它,请使用setTimeout。而且,这是低效率的。为了提高效率,请存储clientWidth和clientHeight,并且仅在clientWidth和clientHeight更改时重新计算和重绘。
“参考”分辨率的概念使您可以使用一种分辨率来编写所有绘制命令...,它将自动调整为客户端大小,而无需更改绘制代码。
该代码段是不言自明的,但是如果您愿意,可以用英语进行解释:https://medium.com/@doomgoober/resizing-canvas-vector-graphics-without-aliasing-7a1f9e684e4d
答案 12 :(得分:1)
设置初始大小。
const canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
在调整窗口大小时更新大小。
function windowResize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
window.addEventListener('resize', windowResize);
答案 13 :(得分:0)
我认为这应该是我们应该做的:http://www.html5rocks.com/en/tutorials/casestudies/gopherwoord-studios-resizing-html5-games/
function resizeGame() {
var gameArea = document.getElementById('gameArea');
var widthToHeight = 4 / 3;
var newWidth = window.innerWidth;
var newHeight = window.innerHeight;
var newWidthToHeight = newWidth / newHeight;
if (newWidthToHeight > widthToHeight) {
newWidth = newHeight * widthToHeight;
gameArea.style.height = newHeight + 'px';
gameArea.style.width = newWidth + 'px';
} else {
newHeight = newWidth / widthToHeight;
gameArea.style.width = newWidth + 'px';
gameArea.style.height = newHeight + 'px';
}
gameArea.style.marginTop = (-newHeight / 2) + 'px';
gameArea.style.marginLeft = (-newWidth / 2) + 'px';
var gameCanvas = document.getElementById('gameCanvas');
gameCanvas.width = newWidth;
gameCanvas.height = newHeight;
}
window.addEventListener('resize', resizeGame, false);
window.addEventListener('orientationchange', resizeGame, false);
答案 14 :(得分:0)
使用jQuery,您可以跟踪窗口调整大小并使用jQuery更改画布的宽度。
像这样的东西
$( window ).resize(function() {
$("#myCanvas").width($( window ).width())
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">
答案 15 :(得分:0)
首先,您不能使用width和height属性来更改大小(至少以我的方式),因为那样会破坏它。你可以这样做: HTML:
<canvas id = 'myCanvas'></canvas>
JS:
var canvas = document.getElementById('myCanvas');
var W = window.innerWidth;
var H = window.innerHeight;
canvas.width = W;
canvas.height = H;
(请原谅我的错别字,我会经常这样做)
答案 16 :(得分:0)
这对我有用。 伪代码:
// screen width and height
scr = {w:document.documentElement.clientWidth,h:document.documentElement.clientHeight}
canvas.width = scr.w
canvas.height = scr.h
此外,就像devyn所说的那样,您可以将宽度和高度的“ document.documentElement.client”替换为“ inner”:
**document.documentElement.client**Width
**inner**Width
**document.documentElement.client**Height
**inner**Height
它仍然有效。
答案 17 :(得分:-2)
我正在使用sketch.js所以在我为画布运行init命令后,我用jquery更改了宽度和高度。它基于父元素的维度。
$( '#DrawCanvas')。素描()。ATTR( '高度',$( '#DrawCanvas')。亲本()。高度())。ATTR( '宽度',$( '#DrawCanvas' 。).parent()宽度());