El lienzo se estira cuando se usa CSS pero es normal con las propiedades "ancho" / "alto"

194

Tengo 2 lienzos, uno usa atributos HTML widthy heightpara dimensionarlo, el otro usa CSS:

<canvas id="compteur1" width="300" height="300" onmousedown="compteurClick(this.id);"></canvas>
<canvas id="compteur2" style="width: 300px; height: 300px;" onmousedown="compteurClick(this.id);"></canvas>

Compteur1 se muestra como debería, pero no compteur2. El contenido se dibuja usando JavaScript en un lienzo de 300x300.

¿Por qué hay una diferencia de visualización?

texto alternativo

Sirber
fuente

Respuestas:

215

Parece que los atributos widthy heightdeterminan el ancho o la altura del sistema de coordenadas del lienzo, mientras que las propiedades CSS solo determinan el tamaño del cuadro en el que se mostrará.

Esto se explica en http://www.whatwg.org/html#attr-canvas-width (necesita JS) o http://www.whatwg.org/c#attr-canvas-width (probablemente se comerá su computadora) :

El canvaselemento tiene dos atributos para controlar el tamaño del mapa de bits del elemento: widthy height. Estos atributos, cuando se especifican, deben tener valores que sean enteros no negativos válidos . Las reglas para analizar enteros no negativos deben usarse para obtener sus valores numéricos. Si falta un atributo o si el análisis de su valor devuelve un error, se debe utilizar el valor predeterminado. El widthatributo predeterminado es 300 y el heightatributo predeterminado es 150.

SamB
fuente
11
de hecho .. Siempre pensé atributos directos como "ancho" y "alto" quedaron en desuso en las últimas versiones html ..
Sirber
44
Oh, aparentemente se describe bastante bien en whatwg.org/specs/web-apps/current-work/multipage/… (sección #attr-canvas-width). El problema es que hice clic en el error widthantes y fui a la #dom-canvas-widthsección en su lugar. Archivado w3.org/Bugs/Public/show_bug.cgi?id=9469 al respecto.
SamB
3
Tener una API que se parece pero es fundamentalmente diferente a otra (css ancho, alto). Guau.
Ben Aston
1
Es importante distinguirlos cuando desee que el sistema de coordenadas interno sea diferente. (es decir, para pantallas de retina o juegos de 8
bits
1
Esto fue realmente confuso. Intentamos establecer el ancho y la altura en el CSS. Nos tomó 2 días estresándonos para descubrir estas 2 interpretaciones diferentes sobre el ancho y la altura. Just wow ...
NME New Media Entertainment
39

Para configurar widthy heightque necesita, puede usar

canvasObject.setAttribute('width', '475');
fermar
fuente
66
+1 el.setAttribute('width', parseInt($el.css('width')))hizo el truco, gracias
Shanimal
9
¿Qué sucede si quiero que mi lienzo tenga un tamaño relativo? Es decir, ¿cómo imitar una width: 100%;propiedad css?
Maxbester
1
Gran respuesta, pero no olvides agregar el canvasObject.setAttribute ('altura', '123') también.
Tom Wells
No creo que necesite usar .setAttribute () Siempre he usado las propiedades .width y .height
Zorgatone
44
Llanura JavaScript (sin jQuery) utilizando la versión getComputedStyle : canvas.setAttribute('width', window.getComputedStyle(canvas, null).getPropertyValue("width"));. Repita para la altura.
Ben J
25

Para los <canvas>elementos, las reglas CSS widthy heightestablecen el tamaño real del elemento del lienzo que se dibujará en la página. Por otro lado, los atributos HTML de widthy heightestablecen el tamaño del sistema de coordenadas o 'cuadrícula' que utilizará la API de lienzo.

Por ejemplo, considere esto ( jsfiddle ):

var ctx = document.getElementById('canvas1').getContext('2d');
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 30, 30);

var ctx2 = document.getElementById('canvas2').getContext('2d');
ctx2.fillStyle = "red";
ctx2.fillRect(10, 10, 30, 30);
canvas {
  border: 1px solid black;
}
<canvas id="canvas1" style="width: 50px; height: 100px;" height="50" width="100"></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px;" height="50" width="100"></canvas>

A ambos se les ha dibujado lo mismo en relación con las coordenadas internas del elemento de lienzo. Pero en el segundo lienzo, el rectángulo rojo tendrá el doble de ancho porque las reglas de CSS extienden el lienzo como un todo en un área más grande.

Nota: Si las reglas CSS para widthy / o heightno se especifican, el navegador usará los atributos HTML para dimensionar el elemento de manera que 1 unidad de estos valores sea igual a 1px en la página. Si no se especifican estos atributos, los valores predeterminados serán a widthde 300y a heightde 150.

Ben Jackson
fuente
16

El lienzo se estirará si establece el ancho y la altura en su CSS. Si desea manipular dinámicamente la dimensión del lienzo, debe usar JavaScript de esta manera:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');
Lluvia azul
fuente
1
¡Excelente! Gracias por esta respuesta Tuve que poner canvas.setAttributeantes canvas.getContext('2d')para evitar el estiramiento de la imagen.
hhh
6

El navegador utiliza el ancho y el alto del CSS, pero el elemento del lienzo se escala según el ancho y el alto del lienzo. En javascript, lea el ancho y alto de css y configure el ancho y alto del lienzo para eso.

var myCanvas = $('#TheMainCanvas');
myCanvas[0].width = myCanvas.width();
myCanvas[0].height = myCanvas.height();
Russell Harkins
fuente
2

Corrección de Shannimal

var el = $('#mycanvas');
el.attr('width', parseInt(el.css('width')))
el.attr('height', parseInt(el.css('height')))
XaviGuardia
fuente
0

CSS establece el ancho y la altura del elemento de lienzo para que afecte el espacio de coordenadas dejando todo dibujado torcido

Este es mi camino sobre cómo establecer el ancho y la altura con Vanilla JavaScript

canvas.width = numberForWidth

canvas.height = numberForHeight
Anthony Gedeon
fuente
-1

Si desea un comportamiento dinámico basado en, por ejemplo, consultas de medios CSS, no use atributos de ancho y alto de lienzo. Utilice las reglas de CSS y luego, antes de obtener el contexto de representación del lienzo, asigne a los atributos de ancho y alto los estilos de ancho y alto de CSS:

var elem = document.getElementById("mycanvas");

elem.width = elem.style.width;
elem.height = elem.style.height;

var ctx1 = elem.getContext("2d");
...
Manolo
fuente
Está claro que un lienzo obtendrá un tamaño de coordenadas predeterminado (300 x 150) si el tamaño solo se especifica en CSS. Sin embargo, esta sugerencia no funciona para mí, pero la solución a continuación sí.
Por Lindberg
@PerLindberg: esta solución funciona si ha definido un ancho y alto de CSS en píxeles para el elemento de lienzo.
Manolo