html5 Canvas drawimage background + 9 images - javascript

I have a little problem, sometimes work or not work drawimage, i tried to begin with draw background and if drawed then next draw 9 images(sometimes images is this same or not same).
var c = document.getElementById('myCanvas');
var ctx = c.getContext("2d");
$('button').on('click',function(){
var img = new Image();
var img1 = new Image();
var img2 = new Image();
var img3 = new Image();
var img4 = new Image();
var img5 = new Image();
var img6 = new Image();
var img7 = new Image();
var img8 = new Image();
var img9 = new Image();
img.src = $(location).attr('href')+'/img/frames/'+$('#frames option:selected').val();
img1.src = $(location).attr('href')+'/img/mercmain/'+$('#merc1 option:selected').val();
img2.src = $(location).attr('href')+'/img/mercmain/'+$('#merc2 option:selected').val();
img3.src = $(location).attr('href')+'/img/mercmain/'+$('#merc3 option:selected').val();
img4.src = $(location).attr('href')+'/img/mercmain/'+$('#merc4 option:selected').val();
img5.src = $(location).attr('href')+'/img/mercmain/'+$('#merc5 option:selected').val();
img6.src = $(location).attr('href')+'/img/mercmain/'+$('#merc6 option:selected').val();
img7.src = $(location).attr('href')+'/img/mercmain/'+$('#merc7 option:selected').val();
img8.src = $(location).attr('href')+'/img/mercmain/'+$('#merc8 option:selected').val();
img9.src = $(location).attr('href')+'/img/mercmain/'+$('#merc9 option:selected').val();
img.onload = function(){
ctx.clearRect(0, 0, c.width, c.height);
ctx.drawImage(img, 0, 0,307,382);
img1.onload = function(){
ctx.drawImage(img1,$xyframe[0][0],$xyframe[0][1],$xyframe[0][2],$xyframe[0][3]);
};
img2.onload = function(){
ctx.drawImage(img2,$xyframe[1][0],$xyframe[1][1],$xyframe[1][2],$xyframe[1][3]);
};
img3.onload = function(){
ctx.drawImage(img3,$xyframe[2][0],$xyframe[2][1],$xyframe[2][2],$xyframe[2][3]);
};
img4.onload = function(){
ctx.drawImage(img4,$xyframe[3][0],$xyframe[3][1],$xyframe[3][2],$xyframe[3][3]);
};
img5.onload = function(){
ctx.drawImage(img5,$xyframe[4][0],$xyframe[4][1],$xyframe[4][2],$xyframe[4][3]);
};
img6.onload = function(){
ctx.drawImage(img6,$xyframe[5][0],$xyframe[5][1],$xyframe[5][2],$xyframe[5][3]);
};
img7.onload = function(){
ctx.drawImage(img7,$xyframe[6][0],$xyframe[6][1],$xyframe[6][2],$xyframe[6][3]);
};
img8.onload = function(){
ctx.drawImage(img8,$xyframe[7][0],$xyframe[7][1],$xyframe[7][2],$xyframe[7][3]);
};
img9.onload = function(){
ctx.drawImage(img9,$xyframe[8][0],$xyframe[8][1],$xyframe[8][2],$xyframe[8][3]);
};
};
});
and link to test script https://tajkjs-olszam.c9users.io/genform/
and if i remove from img1-9.onload, leave ctx.drawimage(img1-9) and make settimeout from 3 to 5 sec then it's ok but i want without settimeout.
setTimeout(function(){
//img.onload = function(){
ctx.drawImage(img, 0, 0,307,382);
// };
ctx.drawImage(img1,$xyframe[0][0],$xyframe[0][1],$xyframe[0][2],$xyframe[0][3]);
ctx.drawImage(img2,$xyframe[1][0],$xyframe[1][1],$xyframe[1][2],$xyframe[1][3]);
ctx.drawImage(img3,$xyframe[2][0],$xyframe[2][1],$xyframe[2][2],$xyframe[2][3]);
ctx.drawImage(img4,$xyframe[3][0],$xyframe[3][1],$xyframe[3][2],$xyframe[3][3]);
ctx.drawImage(img5,$xyframe[4][0],$xyframe[4][1],$xyframe[4][2],$xyframe[4][3]);
ctx.drawImage(img6,$xyframe[5][0],$xyframe[5][1],$xyframe[5][2],$xyframe[5][3]);
ctx.drawImage(img7,$xyframe[6][0],$xyframe[6][1],$xyframe[6][2],$xyframe[6][3]);
ctx.drawImage(img8,$xyframe[7][0],$xyframe[7][1],$xyframe[7][2],$xyframe[7][3]);
ctx.drawImage(img9,$xyframe[8][0],$xyframe[8][1],$xyframe[8][2],$xyframe[8][3]);
},100);
this code is work but unfortunately I have use settimeout

Try not to draw on each image load. Use counter for loaded images and run draw function on last load. Also Pablo said right thing - set onload listener before set source. This code should run inside your click listener function
var img;
var counter = 0;
var imagesLength = 9;
var images = [];
var backgroundImage = new Image();
var imgFolder = location.href+'/img/mercmain/';
function drawImages(){
ctx.clearRect(0, 0, c.width, c.height);
ctx.drawImage(backgroundImage, 0, 0,307,382); //draw background
for ( var i=0; i<imagesLength ; i++ ){ //draw images
ctx.drawImage(images[i],$xyframe[i][0],$xyframe[i][1],$xyframe[i][2],$xyframe[i][3]);
}
}
function onLoad(){
counter++;
if( counter === imagesLength + 1 ){ // +1 - we must count also background image
drawImages(); // draw all the images at once
}
}
for ( var i=0; i<imagesLength ; i++ ){
img = new Image();
images.push( img ); // push in array before src,
// onload should not fire while image is not in array
img.onload = onLoad; // set onload before src,
// image should not load before onload listener is set
img.src = imgFolder + $('#merc'+ (i+1) +' option:selected').val();
}
// do not forget to set the same for background image
backgroundImage.onload = onLoad;
backgroundImage.src = location.href + '/img/frames/' + $('#frames option:selected').val();

You have a race condition: You are loading all the images at the same time, but if the background image is not the first one to be loaded, you are adding the onload listeners AFTER the images have been loaded, so the event has already happened and the drawing logic is never executed.
Solution? the imgN.onload=function() {...} assignments should be outside the img.onload function:
$('button').on('click',function(){
var img = new Image();
var imgArr=[];
for (var i=0;i<9;i++) {
imgArr[i]=new Image();
}
img.src = $(location).attr('href')+'/img/frames/'+$('#frames option:selected').val();
for (var i=0;i<9;i++) {
imgArr[i].src=$(location).attr('href')+'/img/mercmain/'+$('#merc'+i+' option:selected').val();
}
img.onload = function(){
ctx.clearRect(0, 0, c.width, c.height);
ctx.drawImage(img, 0, 0,307,382);
}
//Here, instead in the previous function
for (var i=0;i<9;i++) {
imgArr[i].onload = function(){
ctx.drawImage(img1,$xyframe[i][0],$xyframe[i][1],$xyframe[i][2],$xyframe[i][3]);
};
}
});

Related

Why is a delay needed when drawing a image into a canvas?

Here is the code:
var spriteFolder = "../../assets/Painter/sprites/";
var sprites = {};
sprites.background = new Image();
sprites.background.src = spriteFolder + "spr_background.jpg";
sprites.cannon_barrel = new Image();
sprites.cannon_barrel.src = spriteFolder + "spr_cannon_barrel.png";
sprites.cannon_red = new Image();
sprites.cannon_red.src = spriteFolder + "spr_cannon_red.png";
sprites.cannon_green = new Image();
sprites.cannon_green.src = spriteFolder + "spr_cannon_green.png";
sprites.cannon_blue = new Image();
sprites.cannon_blue.src = spriteFolder + "spr_cannon_blue.png";
var Canvas2D = {
canvas: undefined,
canvasContext: undefined
};
Canvas2D.initialize = function(canvasName) {
Canvas2D.canvas = document.getElementById(canvasName);
Canvas2D.canvasContext = Canvas2D.canvas.getContext("2d");
};
Canvas2D.clear = function() {
Canvas2D.canvas.clearRect(0, 0, Canvas2D.canvas.width, Canvas2D.canvas.height);
};
Canvas2D.drawImage = function(sprite, position, rotation, origin) {
Canvas2D.canvasContext.save();
Canvas2D.canvasContext.translate(position.x, position.y);
Canvas2D.canvasContext.rotate(rotation);
Canvas2D.canvasContext.drawImage(sprite,
0, 0, sprite.width, sprite.height,
-origin.x, -origin.y, sprite.width, sprite.height
);
Canvas2D.canvasContext.restore();
};
function init() {
Canvas2D.initialize("myCanvas");
setTimeout(function() {
Canvas2D.canvasContext.drawImage(sprites.background, 0, 0);
}, 1000);
}
document.addEventListener("DOMContentLoaded", init);
If I don't use setTimeout, then the image is not drawn. Why?
Because your images were not yet loaded.
Thanks to your 1sec timeout they have enough time to load.
Have a look at this example from MDN https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images
You need to use similar approach - see img.onload()
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function(){
ctx.drawImage(img,0,0);
ctx.beginPath();
ctx.moveTo(30,96);
ctx.lineTo(70,66);
ctx.lineTo(103,76);
ctx.lineTo(170,15);
ctx.stroke();
};
img.src = 'https://mdn.mozillademos.org/files/5395/backdrop.png';
}

Missing image when saving image from canvas

I use this code to save images in Javascript :
function saveImage() {
var canvas = document.getElementById('myPicture');
var ctx = canvas.getContext('2d');
var img = new Image();
ctx.rect(0, 0, 460, 600);
ctx.fillStyle = 'white';
img = new Image();
img.crossOrigin = 'anonymous';
img.src = "http://localhost/upload/abc.jpg";
ctx.drawImage(img,0,0,_item.width(),_item.height());
return canvas.toDataURL("image/jpeg");
}
When i click button save image:
$("#save").on('click', function () {
var rawImageData = saveImage();
$(this).attr('download', 'your_pic_name.jpeg').attr('href', rawImageData);
});
However the result I get is white image.
And I click on the save button again (ie 2 times) then is now right result. how do I can just click one time only?
Thank you.
It is because the first time you click, anchor doesn't have image data url... You may set the url and forget about the click event.
//$("#save").on('click', function () {
var rawImageData = saveImage();
$(this).attr('download', 'your_pic_name.jpeg')
.attr('href', rawImageData);
//});
OR
$("#save").on('click', function () {
var rawImageData = saveImage();
/*$(this).attr('download', 'your_pic_name.jpeg')
.attr('href', rawImageData);*/
window.location=rawImageData;
});
OR alternatively, you need this file to use following code
var canvas = document.getElementById('myPicture');
function saveImage() {
var ctx = canvas.getContext('2d');
var img = new Image();
ctx.rect(0, 0, 460, 600);
ctx.fillStyle = 'white';
img = new Image();
img.crossOrigin = 'anonymous';
img.src = "http://localhost/upload/abc.jpg";
// ctx.fill...
return canvas.toDataURL("image/jpeg");
}
$("#save").on('click', function () {
var rawImageData = saveImage();
var png= Canvas2Image.saveAsPNG(canvas , true);
});
PS: I don't see where you feel canvas with the image...int the saveImage function

draw array of images to the canvas

I am trying to draw an array of images to the canvas element, my data:image is returning an empty image.
var imgArray = ['images/image1.png','images/image2.png'];
for(i = 0; i < 2; i++){
var canvas = document.getElementById('textCanvas');
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.setAtX = i * 10;
imageObj.setAtY = i * 10;
imageObj.onload = function() {
context.drawImage(this, this.setAtX, this.setAtY);
};
}
img = canvas.toDataURL("image/png");
You never set the images' source:
var imageObj = new Image();
imageObj.src = imgArray[i]; // << addeed
imageObj.setAtX = i * 10;
imageObj.setAtY = i * 10;
imageObj.onload = function() {
context.drawImage(this, this.setAtX, this.setAtY);
};

Canvas patterned pie chart with array image

I am trying to make a pie chart made by patterns using some images. But I can't see any images which I am trying to show. What is the problem with the following codes?
<html>
<body>
<canvas width="250" height="250" id="canvas"></canvas>
<script>
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[0].src = 'p2.jpg';
imgArray[1] = new Image();
imgArray[1].src = 'p3.jpg';
imgArray[2] = new Image();
imgArray[2].src = 'p4.jpg';
imgArray[3] = new Image();
imgArray[3].src = 'p5.jpg';
imgArray[4] = new Image();
imgArray[4].src = 'p6.jpg';
//initialize data set
var data = [ 100, 68, 20, 30, 100 ];
var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');
//draw background
c.fillStyle = "white";
c.fillRect(0,0,500,500);
//a list of colors
//calculate total of all data
var total = 0;
for(var i=0; i<data.length; i++) {
total += data[i];
}
var prevAngle = 0;
for(var i=0; i<data.length; i++) {
//fraction that this pieslice represents
var fraction = data[i]/total;
In this step, I dynamically try to put the images into the pie chart, but I think the 'src' usage is wrong.
//calc starting angle
var angle = prevAngle + fraction*Math.PI*2;
var pat=c.createPattern(imgArray[i].src,"repeat");
//draw the pie slice
//create a path
c.beginPath();
c.moveTo(250,250);
c.arc(250,250, 100, prevAngle, angle, false);
c.lineTo(250,250);
c.closePath();
//fill it
c.fillStyle = pat;
c.fill();
//stroke it
c.strokeStyle = "black";
c.stroke();
//update for next time through the loop
prevAngle = angle; </script> </body> </html>
You are correct in your suspicion.
createPattern takes an image object--not a URL.
var pat;
var img=new Image();
img.onload=function(){
pat=c.createPattern(img,"repeat");
// now you can create a path and fill it with `pat`
}
img.src="http://whatever.com/whatever.png";
[ Added image loader code in response to additional question ]
// image loader
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgArray=[];
imageURLs.push("p2.jpg");
imageURLs.push("p3.jpg");
imageURLs.push("p4.jpg");
imageURLs.push("p5.jpg");
imageURLs.push("p6.jpg");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgArray.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
function start(){
// the imgArray[] array now holds fully loaded images
// the imgArray[] are in the same order as imageURLs[]
// imgArray[0] is p2.jpg
// imgArray[1] is p3.jpg
// imgArray[2] is p4.jpg
// imgArray[3] is p5.jpg
// imgArray[4] is p6.jpg
// create your patterns now
}

fill image with other image javascript/html5

I need help with the following resource http://www.filmfans.cz/test/index2.html
I don't know how to change the colours of the pinquen after the click on the sample.
I would like to do something similar as in the following link http://www.pixelbox.sk/fileadmin/Flash/cosmo_2.swf
Here is my code
$(window).load(function(){
var width = $(window).width();
var height = $(window).height();
var c = document.getElementById("a");
var ctx = c.getContext("2d");
var can2 = document.createElement('canvas');
document.body.appendChild(can2)
can2.width = c.width;
can2.height= c.height;
var ctx2 = can2.getContext("2d");
var test= new Image();
test.src = "tux.png";
test.onload = function() {
ctx2.drawImage(test, 0, 0);
}
var img = new Image();
img.src = "2.png";
img.onload = function(){
ctx2.globalCompositeOperation = "source-in";
var pattern = ctx2.createPattern(img, "repeat");
ctx2.fillStyle=pattern;
ctx2.fillRect(0,0,300,300);
}
});
$(document).ready(function () {
$('.klik').click(function() {
var adresa = $(this).children('img').attr('src');
var canvas = document.getElementById("a");
canvas.width = canvas.width;//blanks the canvas
var c = canvas.getContext("2d");
var img = new Image();
img.src = adresa;
img.onload = function(){
var pattern = c.createPattern(img, "repeat");
//c.globalCompositeOperation = "source-in";
c.fillStyle=pattern;
c.fillRect(0,0,300,300);
}
// c.drawImage(img, 0, 0);
//}
//return false;
});
});
</code>
</pre>
Problem solved !
Using a second, temporary canvas with source-in is the right idea:
ctx2.drawImage(test, 0, 0);
ctx2.globalCompositeOperation = 'source-in';
var ptrn = ctx2.createPattern(pattern,'repeat');
ctx2.fillStyle = ptrn;
ctx2.fillRect(0,0,300,300);
ctx.drawImage(can2,0,0)
live example:
http://jsfiddle.net/UcGrC/

Categories