merging multiple <canvas> issue - javascript

I'm designing a simple app for which I need to use multiple globalCompositeOperation, and therefore I need to use multiple hidden items, then merge them to get the final result.
one of the canvas items is used to drawImage() and then use it as an alpha mask.
I assumed that on 2nd canvas if I use to draw 1st canvas, it will copy it exactly so I can add 2nd thing on top of it. It does copy only the fillRect() and ignores the drawImage() function...
Any idea how can I forward entire content of the first canvas to 2nd? I need the masked part to move to the 2nd canvas.
Been stuck on it for hours and need your help. Tried to use toDataUrl("image/png") and then output that into 2nd canvas, but getting same results :(
simplified version under:
http://jsfiddle.net/EbVmm/17/
Thanks
var c1 = document.getElementById("canvas1");
var c2 = document.getElementById("canvas2");
function drawScene(mainColour) {
var ctx = c1.getContext("2d");
var alphaPath = "http://eskarian.com/images/alpha-test.png";
var alphaObj = new Image();
alphaObj.src = alphaPath;
ctx.fillStyle = mainColour;
ctx.fillRect(0, 0, 200, 300);
ctx.globalCompositeOperation = 'xor';
alphaObj.onload = function () {
ctx.drawImage(alphaObj, 0, 0);
};
};
function addScene(colour) {
var ctx2 = c2.getContext("2d");
ctx2.drawImage(c1, 0, 0);
ctx2.globalCompositeOperation = "source-over";
ctx2.fillStyle = colour;
ctx2.fillRect(50, 50, 100, 100);
};

You are trying to use alphaObj before it is fully loaded.
Try something like this:
var c1 = document.getElementById("canvas1");
var c2 = document.getElementById("canvas2");
var alphaPath = "http://eskarian.com/images/alpha-test.png";
var alphaObj = new Image();
alphaObj.onload = function () {
drawScene(mainColour);
addScene(colour)
};
alphaObj.src = alphaPath;
function drawScene(mainColour) {
var ctx = c1.getContext("2d");
ctx.drawImage(alphaObj, 0, 0);
ctx.fillStyle = mainColour;
ctx.fillRect(0, 0, 200, 300);
ctx.globalCompositeOperation = 'xor';
};
function addScene(colour) {
var ctx2 = c2.getContext("2d");
ctx2.drawImage(c1, 0, 0);
ctx2.globalCompositeOperation = "source-over";
ctx2.fillStyle = colour;
ctx2.fillRect(50, 50, 100, 100);
};

Related

Javascript Canvas how to remove a shape or area from an image?

Not sure what I'm doing wrong with this but it doesn't seem to work. I want to remove a shape or symbol from an image by it's location, not by colour.
function crop(leftedge, topedge, wd, ht) {
const imageData = context.getImageData(leftedge, topedge, wd, ht);
const canvas1 = document.createElement("canvas");
const ctx1 = canvas1.getContext('2d');
canvas1.width = wd, canvas1.height = ht;
ctx1.clearRect(0, 0, 50, 50);
ctx1.putImageData(imageData, 0, 0);
return canvas1;
}
For some reason the clearRect doesn't seem to do anything. Not sure what other way there is or if I'm doing this wrong. I tried fillRect as well but no result...the image is displayed with no change.
Tha happens because the order of your operation matters. As it is right now, you're clearing that little 50 pixel square before you're overwriting it with new imageData.
Try this:
function crop(leftedge, topedge, wd, ht) {
const imageData = context.getImageData(leftedge, topedge, wd, ht);
const canvas1 = document.createElement("canvas");
const ctx1 = canvas1.getContext('2d');
canvas1.width = wd, canvas1.height = ht;
ctx1.putImageData(imageData, 0, 0);
ctx1.clearRect(0, 0, 50, 50);
return canvas1;
}

Black canvas instead of image

I have a problem with canvas. Let's say, 1/10 time I have black square instead of my image, on chrome. My code is as follow, how can I modify it in order to avoid this black display?
<canvas id="Canvas" width="954" height="267"></canvas>
<script>
var canvas = document.getElementById('Canvas');
var context = canvas.getContext("2d");
// Map sprite
var mapSprite = new Image();
mapSprite.src = 'image.png';
var main = function () {
draw();
};
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw diagramme
context.drawImage(mapSprite, 0, 0, 954, 267);
}
main();
</script>
EDIT 1: full function draw :
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw diagramme
context.drawImage(mapSprite, 0, 0, nextWidth, nextHeight);
//draw all precedent cross
cross = new Image();
cross.src = "cross.png";
for (var i = 0; i < array_x.length; i++) {
context.drawImage(cross, array_x[i], array_y[i], 10, 10);
}
}
I believe you want to wait until image is loaded.
Replace:
main();
With:
mapSprite.addEventListener('load', main);

A function object can't draw images to an image from a canvas

The title is poorly worded but there's no way to concisely describe the problem. I'm drawing images to the 2D context of a dynamically created canvas. The data of the context is then saved to an image via toDataURL, which is then draw on every frame. The code below is condensed, I will be drawing multiple images to the context, not just one; which is why I'm saving to an image. I will only draw part of the image at once but the image remains constant so I thought this was the best method, if there are alternatives I will happily accept those as answers.
In short: many images drawn on an image. Part of the image draw each frame.
The code below works:
var picture = new Image();
picture.src = "images/tilesheet.png";
var canvas = document.getElementById("background");
var context = canvas.getContext("2d");
function generate(){
var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = canvas.width;
ctx.canvas.height = canvas.height;
ctx.fillStyle = "red";
ctx.rect (0, 0, 40, 40);
ctx.fill();
ctx.drawImage(picture,0,0);
image = new Image();
image.src = ctx.canvas.toDataURL("image/png");
}
function draw(){
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(image, 0,0,100,100,0,0,100,100);
}
function play(){
generate();
setInterval(function(){draw();}, 0.0333);
}
window.onload = function(){
if(picture.complete)play();
else picture.onload = play;
}
<canvas id="background"></canvas>
However this doesn't:
window.Game = {};
canvas = document.getElementById("background");
var tilesheet = new Image();
tilesheet.src = "images/tilesheet.png";
(function(){
function Map(){
this.width = 2736;
this.height = 2736;
this.image = null;
}
Map.prototype.generate = function(){
var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = this.width;
ctx.canvas.height = this.height;
ctx.fillStyle = "red";
ctx.rect (0, 0, 40, 40);
ctx.fill();
ctx.drawImage(tilesheet,0,0);
this.image = new Image();
this.image.setAttribute('crossOrigin', 'anonymous');
this.image.src = ctx.canvas.toDataURL("image/png");
}
Map.prototype.draw = function(context){
context.drawImage(this.image, 0,0, context.canvas.height, context.canvas.height, 0, 0, context.canvas.height, context.canvas.height);
}
Game.Map = Map;
})();
(function(){
var room = new Game.Map();
room.generate();
var draw = function(){
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
room.draw(canvas.getContext("2d"));
}
Game.play = function(){setInterval(function(){draw();}, 0.0333);}
})();
window.onload = function(){
if(tilesheet.complete)Game.play();
else tilesheet.onload = Game.play;
}
<canvas id="background"></canvas>
It seems therefore, that the problem is lying in the fact that I'm using function objects but I'm not sure. What am I doing wrong? There are no errors in the debug console.
Those two have different execution order.
First one:
...
Attach image.onload
Call generate()
...
Second one:
...
Call generate()
Attach image.onload
...
That's why it's not working - generate() expects image to be loaded, however second case order doesn't guarantees it.
Instead of
...
room.generate();
...
Game.play = function(){setInterval(function(){draw();}, 0.0333);}
do this
...
Game.play = function(){
room.generate();
setInterval(function(){draw();}, 0.0333);
}

Circle drawn on canvas isn't round

I have problem creating simple circle. I think code drawing it is writed like it suposed to be, and another problem is with axis. I dont know why but 0x point begins in the middle of the "game screen". How to make game screen 640px/480px?
Fiddle demo | Screenshot
start.wyswietl = (function(){
var dom = start.dom,
$ = dom.$,
gracz = start.gracz,
canvas, ctx,
pUruchomienie = true;
function createBackground(){
var background = document.createElement("canvas");
bgctx = background.getContext("2d");
dom.dodKlase(background, "background");
background.width = 640;
background.height = 480;
background = new Image();
background.onload = function(){
bgctx.drawImage(background, 0, 0);
};
background.src = "../obrazki/tapeta.png";
dom.dodKlase(background, "board-bg");
return background;
}
function rysuj(callback){
var gracz = document.createElement("canvas");
gctx = gracz.getContext("2d");
gctx.fillStyle = "black";
gctx.arc(5, 40, 5, 0, 2*Math.PI);
gctx.fill();
// dom.dodKlase(gracz, "plansza");
dom.dodKlase(gracz, "gracze");
return gracz;
callback();
}
//function ()

virtual canvas putimagedata not working

Am new to concept of virtual canvas, any idea why the below code does not work?
<script type="text/javascript">
$(document).ready(function () {
var c1 = document.createElement('canvas');
var ctx1 = c1.getContext("2d");
var c2 = document.getElementById('Canvas2');
var ctx2 = c2.getContext("2d");
c1.width = c2.width;
c1.height = c2.height;
img1 = new Image();
img1.src = 'A1.png';
img1.onload = function () {
ctx1.drawImage(this, 0, 0);
};
imgdata = ctx1.getImageData(0, 0, c2.width, c2.height);
ctx2.putImageData(imgdata, 0, 0);
});
</script>
<canvas id="Canvas2" style="display:block;position:absolute;background-color:transparent;border:1px solid red;">
Your browser does not support the HTML5 canvas tag.
</canvas>
The concept works if i draw Rectangle or any other objects but when i am loading images it
does not display the images loaded on virtual canvas. As below example works fine.
$(document).ready(function () {
var c1 = document.createElement('canvas');
var ctx1 = c1.getContext("2d");
var c2 = document.getElementById('Canvas2');
var ctx2 = c2.getContext("2d");
c1.width = c2.width;
c1.height = c2.height;
ctx1.fillRect(0, 20, 20, 20);
imgdata = ctx1.getImageData(0, 0, c2.width, c2.height);
ctx2.putImageData(imgdata, 0, 0);
});
You must also wait with getImageData etc. until the image has loaded, so move everything that needs to be done after the image has loaded inside the onload handler (or wrap them in a function called from onload):
img1.onload = function () {
ctx1.drawImage(this, 0, 0);
imgdata = ctx1.getImageData(0, 0, c2.width, c2.height);
ctx2.putImageData(imgdata, 0, 0);
};
If you don't then the image may not be loaded and drawn to canvas when you call getImageData which results in a blank byte array.

Categories