2013-08-03 10 views
7

Nel tentativo di trovare la documentazione per putImageData del contesto tela() metodo, ho trovato cose come questa:Perché canvasImageData non funziona quando si specifica la posizione di destinazione?

context.putImageData (imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight);

(da http://www.w3schools.com/tags/canvas_putimagedata.asp)

Secondo la documentazione che ho letto, X e Y sono un indice nella dell'immagine fonte, mentre dirtyX e dirtyY specificano coordinate nella tela di destinazione in cui per disegnare l'immagine. Tuttavia, come vedrai dall'esempio seguente (e JSFiddle) una chiamata a mettereImageData (imgData, x, y) funziona mentre putImageData (imgData, 0, 0, locX, locY) non lo fa. Non sono sicuro del perché.

EDIT:

Credo che la mia vera domanda è perché la riga superiore dell'immagine è nero, e ci sono solo 7 righe, non 8. Le immagini dovrebbero iniziare in alto a sinistra della tela . Fanno partire a sinistra (e hanno 8 colonne). Perché non iniziano in cima?

Risposta: che è a causa di dividere per 0 su questa linea quando yloc è 0:

xoff = imgWidth/(yLoc/3); 

Il JSFiddle:

http://jsfiddle.net/WZynM/

Codice:

<html> 
    <head> 
     <title>Canvas tutorial</title> 

     <script type="text/javascript"> 
      var canvas; 
      var context; // The canvas's 2d context 

      function setupCanvas() 
      { 
       canvas = document.getElementById('myCanvas'); 
       if (canvas.getContext) 
       { 
        context = canvas.getContext('2d'); 
        context.fillStyle = "black"; // this is default anyway 
        context.fillRect(0, 0, canvas.width, canvas.height); 
       } 
      } 

      function init() 
      { 
       loadImages(); 
       startGating(); 
      } 

      var images = new Array(); 
      var gatingTimer; 
      var curIndex, imgWidth=0, imgHeight; 

       // Load images 
      function loadImages() 
      { 
       for (n = 1; n <= 16; n++) 
       { 
        images[n] = new Image(); 
        images[n].src = "qxsImages/frame" + n + ".png"; 
       // document.body.appendChild(images[n]); 

        console.log("width = " + images[n].width + ", height = " + images[n].height); 
       } 

       curIndex = 1; 
       imgWidth = images[1].width; 
       imgHeight = images[1].height; 
      } 

      function redrawImages() 
      { 
       if (imgWidth == 0) 
        return; 

       curIndex++; 
       if (curIndex > 16) 
        curIndex = 1; 

        // To do later: use images[1].width and .height to layout based on image size 
       for (var x=0; x<8; x++) 
       { 
        for (var y=0; y<8; y++) 
        { 
         //if (x != 1) 
        //  context.drawImage(images[curIndex], x*150, y*100); 
         // context.drawImage(images[curIndex], x*150, y*100, imgWidth/2, imgHeight/2); // scale 
        // else 
          self.drawCustomImage(x*150, y*100); 
        } 
       } 
      } 

      function drawCustomImage(xLoc, yLoc) 
      { 
        // create a new pixel array 
       imageData = context.createImageData(imgWidth, imgHeight); 

       pos = 0; // index position into imagedata array 
       xoff = imgWidth/(yLoc/3); // offsets to "center" 
       yoff = imgHeight/3; 

       for (y = 0; y < imgHeight; y++) 
       { 
        for (x = 0; x < imgWidth; x++) 
        { 
         // calculate sine based on distance 
         x2 = x - xoff; 
         y2 = y - yoff; 
         d = Math.sqrt(x2*x2 + y2*y2); 
         t = Math.sin(d/6.0); 

         // calculate RGB values based on sine 
         r = t * 200; 
         g = 125 + t * 80; 
         b = 235 + t * 20; 

         // set red, green, blue, and alpha: 
         imageData.data[pos++] = Math.max(0,Math.min(255, r)); 
         imageData.data[pos++] = Math.max(0,Math.min(255, g)); 
         imageData.data[pos++] = Math.max(0,Math.min(255, b)); 
         imageData.data[pos++] = 255; // opaque alpha 
        } 
       } 

        // copy the image data back onto the canvas 
       context.putImageData(imageData, xLoc, yLoc);  // Works... kinda 
      // context.putImageData(imageData, 0, 0, xLoc, yLoc, imgWidth, imgHeight); // Doesn't work. Why? 
      } 


      function startGating() 
      { 
       gatingTimer = setInterval(redrawImages, 1000/25); // start gating 
      } 

      function stopGating() 
      { 
       clearInterval(gatingTimer); 
      } 
     </script> 

     <style type="text/css"> 
      canvas { border: 1px solid black; } 
     </style> 
    </head> 

    <body onload="setupCanvas(); init();"> 
     <canvas id="myCanvas" width="1200" height="800"></canvas> 
    </body> 
</html> 

http://jsfiddle.net/WZynM/

+0

Cosa deve essere mostrato? Eseguendo l'esempio qui, ho ottenuto uno sfondo nero con alcune immagini blu con cerchi bianchi al loro interno. Potresti postare un'immagine con il risultato atteso (o qualcosa di simile)? –

+0

La riga superiore dell'immagine è nera, ma dovrebbe contenere alcune delle immagini blu/bianche. –

risposta

9

Hai appena ottenuto le tue coordinate all'indietro.

context.putImageData(imageData, xLoc, yLoc, 0, 0, imgWidth, imgHeight); 

Live Demo

xLoc, e yLoc sono dove si sta mettendo, e 0,0,imgWidth,imgHeight è il dato che si sta mettendo sulla tela.

Another example mostrare questo.

Un sacco di documenti on-line sembrano un po 'contraddittorio, ma per la versione a sette param

putImageData(img, dx, dy, dirtyX, dirtyY, dirtyRectWidth, dirtyRectheight) 

dx e dy sono la vostra destinazione, i prossimi quattro parametri sono i parametri rect sporchi, in pratica il controllo cosa si sta disegnando da la tela di origine. Una delle descrizioni più complete che riesco a trovare è nel libro HTML5 Unleashed di Simon Sarris (pagina 165).

+0

Grazie. Domanda di follow-up quindi: perché ho una fila di nero nella parte superiore della mia tela? Le prime chiamate a mettereImageData() specificano 0,0 come posizioni dx e dy. Quindi la riga più in alto * dovrebbe * avere immagini blu/bianche, ma invece è nera. (E noterai che ci sono solo 7 file in verticale, dove dovrebbe esserci 8.) Hai idea del perché? –

+1

@VernJensen Questo perché di questa linea 'xoff = imgWidth/(yloc/3);' divisione per 0 è gettare via tutta la fila superiore, nulla a che fare con 'putImageData' fortuna. http://jsfiddle.net/loktar/WZynM/5/ L'ho cambiato in 'xoff = imgWidth/3' solo per illustrare. – Loktar

+1

Grazie! Ho trovato la stessa cosa solo ora anche prima di vedere il tuo post. ;-) –

1

Dopo averlo usato di recente, ho scoperto che Loktar di sopra ha trovato un problema MOLTO importante. Fondamentalmente, alcuni documenti di questo metodo online non sono corretti, un esempio particolarmente pericoloso è W3Schools, a cui si rivolgerà un numero di persone come riferimento.

I loro stati di documentazione il seguente:

Sinossi:

  • context.putImageData (imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight);

Argomenti:

  • imgData: Specifica l'oggetto ImageData per rimettere sulla tela
  • x: La coordinata x, in pixel, l'angolo superiore sinistro della ImageData oggetto [WRONG]
  • y: la coordinata y, in pixel, dell'angolo superiore sinistro dell'oggetto ImageData [WRONG]
  • dirtyX: facoltativo. Il valore orizzontale (x), in pixel, in cui posizionare l'immagine sulla tela [ERRATO]
  • dirtyY: opzionale. Il valore verticale (y), in pixel, dove posizionare l'immagine sulla tela [ERRORE]
  • dirtyWidth: facoltativo. La larghezza da utilizzare per disegnare l'immagine sulla tela
  • dirtyHeight: Opzionale. L'altezza da utilizzare per disegnare l'immagine sulla tela

Come Loktar afferma sopra, la sinossi corretta è la seguente:

Trama corretto:

  • context.putImageData (imgData, canvasX, canvasY, srcX, srcY, srcWidth, srcHeight);

Argomenti:

  • imgData: Specifica l'oggetto ImageData per rimettere sulla tela (come in precedenza);
  • canvasX: la coordinata x della posizione sulla CANVAS in cui si sta stampando il proprio imageData;
  • canvasY: la coordinata y della posizione sulla CANVAS in cui si sta progettando il ImageData;
  • srcX: opzionale. La coordinata x dell'angolo in alto a sinistra del tuo ImageData;
  • srcY: opzionale. La coordinata y dell'angolo in alto a sinistra del tuo ImageData;
  • srcWidth: facoltativo. La larghezza del tuo ImageData;
  • srcAltezza: facoltativo. L'altezza del tuo ImageData.

Utilizzare la corretta sinossi sopra, e non avrete i problemi che sono stati riscontrati in precedenza.

Darò una grande mancia a Loktar per averlo scoperto inizialmente, ma ho pensato che fosse opportuno fornire una risposta ampliata nel caso in cui altri si imbattessero nello stesso problema.

Problemi correlati