Le canevas est étiré lors de l'utilisation de CSS mais normal avec les propriétés "largeur" ​​/ "hauteur"

194

J'ai 2 toiles, l'une utilise des attributs HTML widthet heightpour la dimensionner, l'autre utilise du 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 s'affiche comme il se doit, mais pas compteur2. Le contenu est dessiné en utilisant JavaScript sur une toile 300x300.

Pourquoi y a-t-il une différence d'affichage?

texte alternatif

Sirber
la source

Réponses:

215

Il semble que le widthetheight attributs déterminent la largeur ou la hauteur du système de coordonnées du canevas, tandis que les propriétés CSS déterminent simplement la taille de la boîte dans laquelle il sera affiché.

Ceci est expliqué sur http://www.whatwg.org/html#attr-canvas-width (nécessite JS) ou http://www.whatwg.org/c#attr-canvas-width (mangera probablement votre ordinateur) :

L' canvasélément possède deux attributs pour contrôler la taille du bitmap de l'élément: widthet height. Ces attributs, lorsqu'ils sont spécifiés, doivent avoir des valeurs qui sont des entiers non négatifs valides . Les règles d'analyse des entiers non négatifs doivent être utilisées pour obtenir leurs valeurs numériques. Si un attribut est manquant ou si l'analyse de sa valeur renvoie une erreur, la valeur par défaut doit être utilisée à la place. L' widthattribut par défaut est 300 et l' heightattribut par défaut 150.

SamB
la source
11
en effet .. j'ai toujours pensé que les attributs directs comme "largeur" ​​et "hauteur" étaient dépréciés dans les dernières versions html ..
Sirber
4
Oh, apparemment, cela est plutôt bien décrit sur whatwg.org/specs/web-apps/current-work/multipage/… (section #attr-canvas-width). Le problème est que j'ai cliqué sur le mauvais widthavant et suis allé à la #dom-canvas-widthplace à la place. Classé w3.org/Bugs/Public/show_bug.cgi?id=9469 à ce sujet.
SamB
3
Avoir une API qui ressemble mais qui est fondamentalement différente d'une autre (largeur css, hauteur). Sensationnel.
Ben Aston
1
Il est important de les distinguer lorsque vous souhaitez que le système de coordonnées interne soit différent. (c.-à-d. pour les affichages de la rétine ou les jeux de style 8 bits)
Samy Bencherif
1
C'était vraiment déroutant. Nous avons essayé de définir la largeur et la hauteur dans le CSS. Il nous a fallu 2 jours de stress pour tirer les cheveux pour découvrir ces 2 interprétations différentes de la largeur et de la hauteur. Juste wow ...
NME New Media Entertainment
39

Pour définir le widthet dont heightvous avez besoin, vous pouvez utiliser

canvasObject.setAttribute('width', '475');
fermar
la source
6
+1 a el.setAttribute('width', parseInt($el.css('width')))fait l'affaire, merci
Shanimal
9
Et si je veux que ma toile ait une taille relative? Autrement dit, comment imiter une width: 100%;propriété CSS?
Maxbester
1
Excellente réponse, mais n'oubliez pas d'ajouter le canvasObject.setAttribute ('height', '123') aussi!
Tom Wells
Je ne pense pas que vous ayez besoin d'utiliser .setAttribute () J'ai toujours utilisé les propriétés .width et .height
Zorgatone
4
JavaScript simple (sans jQuery) en utilisant la version getComputedStyle : canvas.setAttribute('width', window.getComputedStyle(canvas, null).getPropertyValue("width"));. Répétez l'opération pour la hauteur.
Ben J
25

Pour les <canvas>éléments, les règles CSS widthet heightdéfinissent la taille réelle de l'élément de canevas qui sera dessiné sur la page. D'autre part, les attributs HTML widthet heightdéfinissent la taille du système de coordonnées ou de la «grille» que l'API Canvas utilisera.

Par exemple, considérez ceci ( 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>

Les deux ont eu la même chose dessinée sur eux par rapport aux coordonnées internes de l'élément canvas. Mais dans le deuxième canevas, le rectangle rouge sera deux fois plus large car le canevas dans son ensemble est étiré sur une zone plus grande par les règles CSS.

Remarque: Si les règles CSS pour widthet / ou heightne sont pas spécifiées, le navigateur utilisera les attributs HTML pour dimensionner l'élément de telle sorte qu'une unité de ces valeurs soit égale à 1 px sur la page. Si ces attributs ne sont pas spécifiés, ils seront par défaut à un widthde 300et un heightde 150.

Ben Jackson
la source
16

La toile sera étirée si vous définissez la largeur et la hauteur dans votre CSS. Si vous souhaitez manipuler dynamiquement la dimension du canevas, vous devez utiliser JavaScript comme ceci:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');
Pluie bleue
la source
1
Génial! Merci pour cette réponse. J'ai dû mettre canvas.setAttributeavant canvas.getContext('2d')pour éviter d'étirer l'image.
hhh
6

Le navigateur utilise la largeur et la hauteur css, mais l'élément canvas est mis à l'échelle en fonction de la largeur et de la hauteur du canevas. En javascript, lisez la largeur et la hauteur css et définissez la largeur et la hauteur du canevas à cela.

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

Correction Shannimal

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

CSS définit la largeur et la hauteur de l'élément canvas afin qu'il affecte l'espace de coordonnées, laissant tout dessiné de travers

Voici ma façon de définir la largeur et la hauteur avec Vanilla JavaScript

canvas.width = numberForWidth

canvas.height = numberForHeight
Anthony Gedeon
la source
-1

Si vous souhaitez un comportement dynamique basé, par exemple, sur des requêtes multimédia CSS, n'utilisez pas d'attributs de largeur et de hauteur du canevas. Utilisez les règles CSS, puis, avant d'obtenir le contexte de rendu du canevas, attribuez aux attributs largeur et hauteur les styles CSS largeur et hauteur:

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

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

var ctx1 = elem.getContext("2d");
...
Manolo
la source
Il est clair qu'un canevas obtiendra une taille de coordonnées par défaut (300 x 150) si la taille n'est spécifiée qu'en CSS. Cependant, cette suggestion ne fonctionne pas pour moi, mais la solution ci-dessous le fait.
Per Lindberg
@PerLindberg - Cette solution fonctionne si vous avez défini une largeur et une hauteur CSS en pixels pour l'élément canvas.
Manolo