A tela é esticada ao usar CSS, mas é normal com as propriedades "width" / "height"

194

Eu tenho 2 telas, uma usa atributos HTML widthe heightpara dimensioná-la, a outra 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>

O Compteur1 é exibido como deveria, mas não o compteur2. O conteúdo é desenhado usando JavaScript em uma tela de 300 x 300.

Por que há uma diferença de exibição?

texto alternativo

Sirber
fonte

Respostas:

215

Parece que os atributos widthe heightdeterminam a largura ou a altura do sistema de coordenadas da tela, enquanto as propriedades CSS apenas determinam o tamanho da caixa na qual será mostrado.

Isso é explicado em http://www.whatwg.org/html#attr-canvas-width (precisa de JS) ou http://www.whatwg.org/c#attr-canvas-width (provavelmente consumirá seu computador) :

O canvaselemento possui dois atributos para controlar o tamanho do bitmap do elemento: widthe height. Esses atributos, quando especificados, devem ter valores que são números inteiros não negativos válidos . As regras para analisar números inteiros não negativos devem ser usadas para obter seus valores numéricos. Se um atributo estiver ausente ou se a análise de seu valor retornar um erro, o valor padrão deverá ser usado. O widthatributo padrão é 300 e o heightatributo padrão é 150.

SamB
fonte
11
na verdade .. Eu sempre pensei atributos diretos como "width" e "height" foram depreciado em versões recentes do HTML ..
Sirber
4
Ah, aparentemente está realmente bem descrito em whatwg.org/specs/web-apps/current-work/multipage/… (seção #attr-canvas-width). O problema é que eu cliquei no errado widthantes e fui para a #dom-canvas-widthseção. Arquivado em w3.org/Bugs/Public/show_bug.cgi?id=9469 sobre isso.
SamB
3
Ter uma API que se parece, mas é fundamentalmente diferente de outra (largura, altura do CSS). Uau.
Ben Aston
1
É importante diferenciá-los para momentos em que você deseja que o sistema de coordenadas interno seja diferente. (ou seja, para telas Retina ou estilo de jogo de 8 bits)
Samy Bencherif
1
Isso foi realmente confuso. Estamos onde tentando definir a largura e a altura no css. Demorou 2 dias para puxar o cabelo para descobrir essas duas interpretações diferentes sobre largura e altura. Apenas uau ...
NME New Media Entertainment
39

Para definir widthe heightvocê precisa, você pode usar

canvasObject.setAttribute('width', '475');
fermar
fonte
6
+1 el.setAttribute('width', parseInt($el.css('width')))fez o truque, graças
Shanimal
9
E se eu quiser que minha tela tenha um tamanho relativo? Ou seja, como imitar uma width: 100%;propriedade css?
Maxbester
1
Ótima resposta, mas não esqueça de adicionar também o canvasObject.setAttribute ('height', '123')!
Tom Wells
Eu não acho que você precisa usar .setAttribute () Eu sempre usei as propriedades .Width e .Height
Zorgatone
4
Plain JavaScript (sem jQuery) versão usando getComputedStyle : canvas.setAttribute('width', window.getComputedStyle(canvas, null).getPropertyValue("width"));. Repita para a altura.
21417 Ben Ben
25

Para <canvas>elementos, o CSS governa widthe heightdefine o tamanho real do elemento da tela que será desenhado na página. Por outro lado, os atributos HTML widthe heightdefinem o tamanho do sistema de coordenadas ou da 'grade' que a API da tela usará.

Por exemplo, considere isso ( 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>

Ambos tiveram a mesma coisa desenhada em relação às coordenadas internas do elemento canvas. Mas na segunda tela, o retângulo vermelho terá o dobro da largura porque a tela como um todo está sendo esticada por uma área maior pelas regras do CSS.

Nota: Se as regras de CSS para widthe / ou heightnão forem especificadas, o navegador usará os atributos HTML para dimensionar o elemento, de modo que 1 unidade desses valores seja igual a 1px na página. Se esses atributos não forem especificados, eles serão padronizados como a widthde 300e a heightde 150.

Ben Jackson
fonte
16

A tela será esticada se você definir a largura e a altura no seu CSS. Se você deseja manipular dinamicamente a dimensão da tela, use o JavaScript da seguinte forma:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');
Chuva azul
fonte
1
Ótimo! Obrigado por esta resposta. Eu tive que colocar canvas.setAttributeantes canvas.getContext('2d')para evitar o alongamento da imagem.
hhh
6

O navegador usa a largura e a altura do CSS, mas o elemento da tela é dimensionado com base na largura e altura da tela. Em javascript, leia a largura e a altura do CSS e defina a largura e a altura da tela para isso.

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

Correção Shannimal

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

O CSS define a largura e a altura do elemento da tela, de modo que afeta o espaço das coordenadas, deixando tudo o que está distorcido

Aqui está o meu caminho sobre como definir a largura e a altura com Vanilla JavaScript

canvas.width = numberForWidth

canvas.height = numberForHeight
Anthony Gedeon
fonte
-1

Se você deseja um comportamento dinâmico baseado em, por exemplo, consultas de mídia CSS, não use atributos de largura e altura da tela. Use regras CSS e, em seguida, antes de obter o contexto de renderização da tela, atribua aos atributos width e height os estilos CSS width e height:

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

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

var ctx1 = elem.getContext("2d");
...
Manolo
fonte
É claro que uma tela terá um tamanho de coordenada padrão (300 x 150) se o tamanho for especificado apenas em CSS. No entanto, essa sugestão não funciona para mim, mas a solução abaixo funciona.
Per Lindberg
@PerLindberg - Esta solução funciona se você definiu uma largura e altura CSS em pixels para o elemento canvas.
Manolo