web-dev-qa-db-fra.com

Comment redimensionner un élément de toile html?

J'ai un élément de toile défini de manière statique dans le HTML avec une largeur et une hauteur. Si j'essaie d'utiliser JavaScript pour le redimensionner dynamiquement (en définissant une nouvelle largeur et une nouvelle hauteur - soit sur les attributs du canevas, soit via les propriétés du style), l'erreur suivante apparaît dans Firefox:

exception non capturée: [Exception ... "Opération illégale sur l'objet prototype WrappedNative" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" emplacement: "JS frame :: file: ///home/russh/Desktop/test.html :: onclick :: ligne 1 "données: non]

Est-il possible de redimensionner cet élément ou dois-je le détruire et créer un nouvel élément à la volée? 

43
russx2

Vous n'avez pas publié votre code et je suppose que vous faites quelque chose de mal. il est possible de changer la taille en attribuant des attributs de largeur et de hauteur à l'aide de nombres:

canvasNode.width  = 200; // in pixels
canvasNode.height = 100; // in pixels

Au moins ça marche pour moi. Veillez à ne pas attribuer de chaînes (par exemple, "2 cm", "3 pouces" ou "2,5 pixels") et à ne pas jouer avec les styles.

En réalité, il s’agit d’une connaissance accessible au public - vous pouvez tout lire à ce sujet dans les spécifications de la toile HTML - elle est très petite et particulièrement informative. C'est toute l'interface DOM:

interface HTMLCanvasElement : HTMLElement {
           attribute unsigned long width;
           attribute unsigned long height;

  DOMString toDataURL();
  DOMString toDataURL(in DOMString type, [Variadic] in any args);

  DOMObject getContext(in DOMString contextId);
};

Comme vous pouvez le voir, il définit 2 attributs width et height, et les deux sont unsigned long.

63
Eugene Lazutkin

Notez que si votre canevas est déclaré de manière statique, vous devez utiliser les attributs width et height et non le style, eg. cela fonctionnera:

<canvas id="c" height="100" width="100" style="border:1px"></canvas>
<script>
    document.getElementById('c').width = 200;
</script>

Mais cela va pas fonctionner:

<canvas id="c" style="width: 100px; height: 100px; border:1px"></canvas>
<script>
    document.getElementById('c').width = 200;
</script>
20
sam hocevar

Je viens d'avoir le même problème que vous, mais découvert la méthode toDataURL, qui s'est avéré utile.

L’essentiel est de transformer votre toile actuelle en une URL de données, de modifier la taille de votre toile, puis de dessiner ce que vous aviez dans votre toile à partir de la URL de données que vous avez enregistrée.

Alors voici mon code:

var oldCanvas = canvas.toDataURL("image/png");
var img = new Image();
img.src = oldCanvas;
img.onload = function (){
    canvas.height += 100;
    ctx.drawImage(img, 0, 0);
}
14
john
<div id="canvasdiv" style="margin: 5px; height: 100%; width: 100%;">
    <canvas id="mycanvas" style="border: 1px solid red;"></canvas>
</div>
<script>
$(function(){
    InitContext();
});
function InitContext()
{
var $canvasDiv = $('#canvasdiv');

var canvas = document.getElementById("mycanvas");
canvas.height = $canvasDiv.innerHeight();
canvas.width = $canvasDiv.innerWidth();
}
</script>
5
Jignesh Variya

Cela a fonctionné pour moi tout à l'heure:

<canvas id="c" height="100" width="100" style="border:1px solid red"></canvas>
<script>
var c = document.getElementById('c');
alert(c.height + ' ' + c.width);
c.height = 200;
c.width = 200;
alert(c.height + ' ' + c.width);
</script>
3
Kent Brewster

Voici mon effort pour donner une réponse plus complète (en s'appuyant sur la réponse de @ john).

Le problème initial rencontré était la modification de la largeur et de la hauteur d'un nœud de la zone de dessin (à l'aide de styles). Le contenu était alors simplement "zoomé" ou "réduit". Ce n'était pas l'effet désiré.

Supposons donc que vous souhaitiez dessiner deux rectangles de taille arbitraire dans un canevas de 100 pixels par 100 pixels.

<canvas width="100" height="100"></canvas>

Pour vous assurer que les rectangles ne dépassent pas la taille de la toile et ne sont donc pas visibles, vous devez vous assurer que la toile est suffisamment grande.

var $canvas = $('canvas'),
    oldCanvas,
    context = $canvas[0].getContext('2d');

function drawRects(x, y, width, height)
{
  if (($canvas.width() < x+width) || $canvas.height() < y+height)
  {
    oldCanvas = $canvas[0].toDataURL("image/png")
    $canvas[0].width = x+width;
    $canvas[0].height = y+height;

    var img = new Image();
    img.src = oldCanvas;
    img.onload = function (){
      context.drawImage(img, 0, 0);
    };
  }
  context.strokeRect(x, y, width, height);
}


drawRects(5,5, 10, 10);
drawRects(15,15, 20, 20);
drawRects(35,35, 40, 40);
drawRects(75, 75, 80, 80);

Enfin, voici le jsfiddle pour ceci: http://jsfiddle.net/Rka6D/4/ .

1
Gezim

Les prototypes peuvent être un travail fastidieux, et d'après la partie _PROTO de l'erreur, il semble que votre erreur soit due, par exemple, à HTMLCanvasElement.prototype.width, éventuellement en tentant de redimensionner toutes les toiles à la fois.

À titre de suggestion, si vous essayez de redimensionner plusieurs toiles à la fois, vous pouvez essayer:

<canvas></canvas>
<canvas></canvas>
<canvas></canvas>
<script type="text/javascript">
    ...
</script>

Dans le code JavaScript, au lieu d’invoquer un prototype, essayez ceci:

$$ = function(){
    return document.querySelectorAll.apply(document,arguments);
}
for(var i in $$('canvas')){
    canvas = $$('canvas')[i];
    canvas.width = canvas.width+100;
    canvas.height = canvas.height+100;
}

Cela redimensionnerait toutes les toiles en ajoutant 100 px à leur taille, comme indiqué dans cet exemple


J'espère que cela a aidé.

0
Braden Best