2016-04-14 6 views
0

In einem HTML-Dokument habe ich eine Leinwand mit einem Hintergrundbild und zeichne eine Form und speichere sie als ein Objekt und lege sie dann als Element der Leinwand wieder ein. So wie es jetzt aussieht, wird beim Einfügen der Form als Canvas-Element ein Teil der Leinwand über den Hintergrund gelegt, sodass die Form von der Farbe der Leinwand umgeben ist, anstatt über den Canvas-Hintergrund gezogen zu werden. Gibt es eine Möglichkeit, dies zu vermeiden, aber trotzdem das Bild einfügen zu können, wo ich es möchte? (Ich weiß, ich könnte das Bild als PNG speichern und dann den Hintergrund transparent machen, aber ich würde es gerne im HTML selbst machen.) Ich habe ein paar Dinge gesehen, die tangierend sind, aber keine, die ich gefunden habe adressiere es direkt.Gezeichnete Form über Leinwand setzen Hintergrundbild

Fiddle: https://jsfiddle.net/ZLevine/h3mo50w8/4/

I verwendeten Beispielcode aus https://msdn.microsoft.com/en-us/library/gg589516(v=vs.85).aspx die Form zu zeichnen.

-Code in Geige:

<html> 
<head> 
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> 
<style> 
canvas { 
    border:1px solid #d3d3d3; 
    background-image: white; 
    } 
</style> 
<head> 
    <body onload="startGame()"> 

    <script> 
    var ship = new Image(); 
    var myBackground; 

    function startGame() { 
     myBackground = new component(656, 541, "http://wallpapercave.com/wp/PU5vVEd.jpg", 0, 0, "background"); 
     myScore = new component("30px", "Consolas", "white", 280, 40, "text"); 
     myGameArea.start(); 
     makeShip(); 
    } 

    var myGameArea = { 
     canvas : document.createElement("canvas"), 
     start : function() { 
      this.canvas.width = 480; 
      this.canvas.height = 540; 
      this.context = this.canvas.getContext("2d"); 
      document.body.insertBefore(this.canvas, document.body.childNodes[0]); 
      this.frameNo = 0; 
      this.interval = setInterval(updateGameArea, 20); 
      }, 
     clear : function() { 
      this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 
     }, 
     stop : function() { 
      clearInterval(this.interval); 
     } 
    } 

    function makeShip() { 
    ctx = myGameArea.context 
      // Draw saucer bottom. 
      ctx.beginPath(); 
      ctx.moveTo(28.4, 16.9); 
      ctx.bezierCurveTo(28.4, 19.7, 22.9, 22.0, 16.0, 22.0); 
      ctx.bezierCurveTo(9.1, 22.0, 3.6, 19.7, 3.6, 16.9); 
      ctx.bezierCurveTo(3.6, 14.1, 9.1, 11.8, 16.0, 11.8); 
      ctx.bezierCurveTo(22.9, 11.8, 28.4, 14.1, 28.4, 16.9); 
      ctx.closePath(); 
      ctx.fillStyle = "rgb(222, 103, 0)"; 
      ctx.fill(); 

      // Draw saucer top. 
      ctx.beginPath(); 
      ctx.moveTo(22.3, 12.0); 
      ctx.bezierCurveTo(22.3, 13.3, 19.4, 14.3, 15.9, 14.3); 
      ctx.bezierCurveTo(12.4, 14.3, 9.6, 13.3, 9.6, 12.0); 
      ctx.bezierCurveTo(9.6, 10.8, 12.4, 9.7, 15.9, 9.7); 
      ctx.bezierCurveTo(19.4, 9.7, 22.3, 10.8, 22.3, 12.0); 
      ctx.closePath(); 
      ctx.fillStyle = "rgb(51, 190, 0)"; 
      ctx.fill(); 
      // Save ship data. 
      ship = ctx.getImageData(0, 0, 30, 30); 

      } 

    function component(width, height, color, x, y, type) { 
     this.type = type; 
     if (type == "image" || type == "background") { 
     this.image = new Image(); 
     this.image.src = color; 
     } 
     this.width = width; 
     this.height = height; 
     this.speedX = 0; 
     this.speedY = 0;  
     this.x = x; 
     this.y = y;  
     this.update = function() { 
      ctx = myGameArea.context; 
      if (this.type == "text") { 
      ctx.font = this.width + " " + this.height; 
      ctx.fillStyle = color; 
      ctx.fillText(this.text, this.x, this.y); 
     } if (type == "image" || type == "background") { 
      ctx.drawImage(this.image, 
      this.x, 
      this.y, 
      this.width, this.height); 
      if (type == "background") { 
      ctx.drawImage(this.image, this.x, 
      this.y - this.height, 
      this.width, this.height); 
      } 
     } 
     else { 
      ctx.fillStyle = color; 
      ctx.fillRect(this.x, this.y, this.width, this.height); 
     } 
    } 
     this.newPos = function() { 
      this.x += this.speedX; 
      this.y += this.speedY; 
      if (this.type == "background") { 
       if (this.y == (this.height)) { 
        this.y = 0; 
       } 
      }  
     }  
    } 

    function updateGameArea() { 
     myGameArea.clear(); 
     myBackground.speedY = 1; 
     myBackground.newPos();  
     myBackground.update(); 
     myGameArea.frameNo += 1; 
     ctx.putImageData(ship, 200, 200); 
    } 

    function everyinterval(n) { 
     if ((myGameArea.frameNo/n) % 1 == 0) {return true;} 
     return false; 
    } 


    </script> 
    </div> 
    </body> 
</html> 
+0

aktualisiert fiddle: https://jsfiddle.net/ZLevine/h3mo50w8/4/, wird auch Code in der Post selbst hinzufügen – ZLevine

Antwort

1

Das Problem ist, dass die Verwendung von putImageData() wird wörtlich, was Sie als ImageData als u gespeichert singen getImageData(). Da das Schiff von transparenten Pixeln umgeben ist, werden auch diese auf die Leinwand kopiert und überschreiben, was dort ist.

Wie MarkE in seiner Antwort erwähnt, ist das Zeichnen auf eine temporäre Leinwand eine bessere Lösung. Alles, was Sie tun müssen, ist ein paar Stellen im Code zu ändern:

// Save ship data. 
//ship = ctx.getImageData(0, 0, 30, 30); 
ship = document.createElement("canvas"); // create canvas 
ship.width = ship.height = 30;   // set size 
var shipCtx = ship.getContext("2d");  // temp. context 
shipCtx.drawImage(ctx.canvas, 0, 0);  // draw ship to canvas 

Dann, wenn Sie es zurück ziehen wollen:

function updateGameArea() { 
    myGameArea.clear(); 
    myBackground.speedY = 1; 
    myBackground.newPos();  
    myBackground.update(); 
    myGameArea.frameNo += 1; 
    //ctx.putImageData(ship, 200, 200); 
    ctx.drawImage(ship, 200, 200);  // draw ship from canvas 
} 

Updated fiddle

Ein alternativer Ansatz ist um die Form direkt auf die Leinwand zu zeichnen, aber die Verwendung einer Zwischenfläche bietet Leistungsvorteile.

1

Zeichnen Sie das Schiff auf eine zweite Speicher Leinwand:

var memCanvas=document.createElement('canvas'); 
... draw your ship on the second canvas 

Dann die zweite Leinwand benutzen Sie Ihr Schiff auf der großen Leinwand zu zeichnen:

canvas.drawImage(memCanvas,x,y);