¿Cómo puedo escalar automáticamente el <canvas>
elemento HTML5 para que se ajuste a la página?
Por ejemplo, puedo obtener una <div>
escala ajustando las propiedades height
y width
al 100%, pero una <canvas>
escala no, ¿verdad?
¿Cómo puedo escalar automáticamente el <canvas>
elemento HTML5 para que se ajuste a la página?
Por ejemplo, puedo obtener una <div>
escala ajustando las propiedades height
y width
al 100%, pero una <canvas>
escala no, ¿verdad?
Respuestas:
Creo que he encontrado una solución elegante para esto:
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;
}
No ha tenido ningún gran impacto negativo en el rendimiento para mí, hasta ahora.
body, html { margin: 0px;}
La siguiente solución me funcionó mejor. Como soy relativamente nuevo en la codificación, me gusta tener una confirmación visual de que algo funciona de la manera que espero. Lo encontré en el siguiente sitio: http://htmlcheats.com/html/resize-the-html5-canvas-dyamically/
Aquí está el código:
<!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>
El borde azul muestra el borde del lienzo de cambio de tamaño, y siempre está a lo largo del borde de la ventana, visible en los 4 lados, lo cual NO fue el caso para algunas de las otras respuestas anteriores. Espero eso ayude.
overflow: hidden
y display: block
es lo que faltaba para que esto funcionara correctamente.
Básicamente, lo que tiene que hacer es vincular el evento onresize a su cuerpo, una vez que capta el evento solo necesita cambiar el tamaño del lienzo usando window.innerWidth y 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>
Establecer el ancho y la altura del espacio de coordenadas del lienzo en función de las dimensiones del cliente del navegador requiere que cambie el tamaño y vuelva a dibujar cada vez que cambie el tamaño del navegador.
Una solución menos complicada es mantener las dimensiones dibujables en las variables de Javascript, pero establecer las dimensiones del lienzo en función de las dimensiones screen.width, screen.height. Use CSS para encajar:
#containingDiv {
overflow: hidden;
}
#myCanvas {
position: absolute;
top: 0px;
left: 0px;
}
La ventana del navegador generalmente nunca será más grande que la pantalla en sí misma (excepto donde la resolución de la pantalla no se informa correctamente, ya que podría ser con monitores duales no coincidentes), por lo que el fondo no se mostrará y las proporciones de píxeles no variarán. Los píxeles del lienzo serán directamente proporcionales a la resolución de la pantalla a menos que use CSS para escalar el lienzo.
Un enfoque CSS puro que se agrega a la solución de @jerseyboy anterior.
Funciona en Firefox (probado en v29), Chrome (probado en v34) e Internet Explorer (probado en 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>
Enlace al ejemplo: http://temporaer.net/open/so/140502_canvas-fit-to-window.html
Pero tenga cuidado, como dice @jerseyboy en su comentario:
Cambiar el tamaño del lienzo con CSS es problemático. Al menos en Chrome y Safari, las posiciones de eventos de mouse / touch no se corresponderán 1: 1 con las posiciones de píxeles del lienzo, y tendrá que transformar los sistemas de coordenadas.
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);
A menos que desee que el lienzo aumente la escala de sus datos de imagen automáticamente (de eso es de lo que habla la respuesta de James Black, pero no se verá bonito), debe cambiar el tamaño usted mismo y volver a dibujar la imagen. Centrando un lienzo
Si su div llenó completamente la página web, entonces puede llenar ese div y así tener un lienzo que llena el div.
Puede encontrar esto interesante, ya que puede necesitar usar un CSS para usar el porcentaje, pero depende de qué navegador esté usando y de cuánto esté de acuerdo con la especificación: http://www.whatwg.org/ specs / web-apps / current-work / multipage / the-canvas-element.html # the-canvas-element
Las dimensiones intrínsecas del elemento canvas son iguales al tamaño del espacio de coordenadas, con los números interpretados en píxeles CSS. Sin embargo, el elemento puede ser dimensionado arbitrariamente por una hoja de estilo. Durante el renderizado, la imagen se escala para adaptarse a este tamaño de diseño.
Es posible que deba obtener el offsetWidth y la altura del div, u obtener la altura / ancho de la ventana y establecerlo como el valor de píxel.
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();
});
Si está interesado en preservar las relaciones de aspecto y hacerlo en CSS puro (dada la relación de aspecto), puede hacer algo como a continuación. La clave está padding-bottom
en el ::content
elemento que dimensiona el container
elemento. Esto tiene un tamaño relativo al ancho de su padre, que es 100%
por defecto. La proporción especificada aquí tiene que coincidir con la proporción de los tamaños en el canvas
elemento.
// 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);
/*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%;
}
<!-- HTML -->
<div class=container>
<div class=wrapper>
<canvas width=1200 height=600></canvas>
</div>
</div>
Usando jQuery puedes rastrear el tamaño de la ventana y cambiar el ancho de tu lienzo usando jQuery también.
Algo como eso
$( 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;">
(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();
});
}());
Creo que esto es exactamente lo que debemos hacer: 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);
Estoy usando sketch.js, así que después de ejecutar el comando init para el lienzo, cambio el ancho y la altura con jquery. Basa las dimensiones en el elemento padre.
$ ('# DrawCanvas'). Sketch (). Attr ('height', $ ('# DrawCanvas'). Parent (). Height ()). Attr ('width', $ ('# DrawCanvas'). Parent ().anchura());