2008-12-01 22 views
37

Tengo un elemento canvas definido estáticamente en el html con ancho y alto. Si intento utilizar JavaScript para cambiar su tamaño de forma dinámica (el establecimiento de una nueva anchura y altura - ya sea en los atributos de la tela oa través de las propiedades de estilo) me sale el siguiente error en Firefox:Cómo cambiar el tamaño del elemento de lienzo html?

excepción no detectada: [Excepción ... "Operación ilegal en el objeto prototipo WrappedNative" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" ubicación: datos "JS frame :: file: ///home/russh/Desktop/test.html :: onclick :: line 1": no]

¿Es posible cambiar el tamaño de este elemento o tengo que destruirlo y crear un nuevo elemento sobre la marcha?

+0

En realidad, el mensaje de error parece como si hubiera intentado cambiar la propiedad 'width' o' height' de 'HTMLCanvasElement.prototype' directamente. No tengo idea de cómo podría hacerse esto accidentalmente. – Robert

+0

Eche un vistazo a mi implementación: http://stackoverflow.com/a/23128583/1265753 – karaxuna

Respuesta

53

No ha publicado su código, y sospecho que hace algo mal. es posible cambiar el tamaño asignando atributos de ancho y alto usando números:

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

Al menos me sirve. Asegúrese de no asignar cadenas (por ejemplo, "2cm", "3in" o "2.5px"), y no se meta con los estilos.

En realidad este es un conocimiento públicamente disponible — que puede leer todo al respecto en the HTML canvas spec — es muy pequeño e inusualmente informativo. Esta es toda la interfaz 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); 
}; 

Como se puede ver que define atributos width 2 y height, y dos de ellos son unsigned long.

+21

Nota: cuando cambia el tamaño del lienzo, parece borrar el lienzo (al menos en cromo). – RobKohr

+3

sí. Estoy de acuerdo. ¿Hay alguna forma de redimensionar el lienzo y, al mismo tiempo, redimensionar (escalar) las imágenes que contiene? – Alexis

+0

Sería útil publicar un ejemplo de uso de esto en jsfiddle. –

3

Esto funcionó para mí en este momento:

<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> 
+0

Aquí está en jsfiddle: http://jsfiddle.net/J8PyU/ –

14

simplemente tuve el mismo problema que tú, pero descubrí el método toDataURL, que demostró ser útil.

Lo esencial es convertir su lienzo actual en una URL de datos, cambiar el tamaño de su lienzo y luego dibujar lo que tenía en su lienzo desde la URL de datos que guardó.

Así que aquí es mi código:

var oldCanvas = canvas.toDataURL("image/png"); 
var img = new Image(); 
img.src = oldCanvas; 
img.onload = function(){ 
    canvas.height += 100; 
    ctx.drawImage(img, 0, 0); 
} 
+4

ctx.getImageData() y ctx.putImageData() son más livianos y están diseñados para esta tarea. – fuzzyTew

+0

@fuzzyTew Estoy bastante seguro de que usar '' 'getImageData()' '' y '' 'putImageData()' '' será eficiente, pero se copiará píxel por píxel, sin escalar los datos de la imagen anterior, mientras se usa '' 'drawImage()' '' permitiría escalar. – snapfractalpop

+0

¿Por qué usar 'toDataUrl'? Esto causa conversión de datos innecesarios (raw => png). En su lugar, podría usar 'drawImage' dos veces. –

1

Aquí está mi esfuerzo para dar una respuesta más completa (sobre la base de @ John respuesta).

El problema inicial que encontré fue cambiar el ancho y la altura de un nodo de lienzo (utilizando estilos), como resultado el contenido solo se "amplió" o "redujo". Este no fue el efecto deseado.

Por lo tanto, supongamos que desea dibujar dos rectángulos de tamaño arbitrario en un lienzo que sea 100px por 100px.

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

Para garantizar que los rectángulos no excederán el tamaño del lienzo y por lo tanto no sea visible, es necesario asegurarse de que la tela es lo suficientemente 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); 

Por último, aquí está la jsFiddle para esto: http://jsfiddle.net/Rka6D/4/.

13

Tenga en cuenta que si su lienzo está estáticamente declarado debe utilizar los atributos width y height, no el estilo, por ejemplo. esto funcionará:

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

Pero esto no trabajo:

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

prototipos puede ser una molestia para trabajar, y desde la parte _PROTO del error que aparece es la causa de su error por ejemplo, HTMLCanvasElement.prototype.width, posiblemente como un intento de cambiar el tamaño de todos los lienzos a la vez.

Como sugerencia, si usted está tratando de cambiar el tamaño de una serie de lienzos a la vez, usted podría intentar:

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

En el JavaScript, en lugar de invocar un prototipo, intente esto:

$$ = 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; 
} 

Esto cambiaría el tamaño de todos los lienzos al agregar 100 px a su tamaño, como se demuestra en this example


Espero que haya sido de ayuda.

5
<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> 
Cuestiones relacionadas