Is there an onload function for html canvas? - javascript

My goal is to create an array of imageData from a series of png images.
In order to do this I use a for loop to go through the images, put them in the canvas and then retrieve and store the created imageData in an array.
The problem is that the image does not have enough time to be loaded in the canvas.
My solution for now is to have a timer leave enough time but it's horrible.
I can't seem to find any solution to this problem. Is there a way to have an "onload" function for the canvas?
for(var i=1;i<50;i++){
(function(i){
setTimeout(function(){
return function(){
var newpath = path+i+".png"; //path to the image
baliseimg.onload = function(){ //baliseimg : html image tag
ctxt.drawImage(baliseimg,0,0);
ctxt.fillText(i, 50, 50); //just to stamp the image number on the imagedata
imgs[i-1]=ctxt.getImageData(0,0,512,512);
}
baliseimg.src=newpath;
}();
},100*i); //100ms works, limit seems to be at 40
}(i));
}
Thank you for your time.

No, according to http://www.w3schools.com/jsref/event_onload.asp
But you still can use img elements' onload in order to do canvas manipulation. This article may help you.
Bonne chance !

Here's code to preload all your images.
When they are fully loaded the start() function is called.
// image loader
var imageURLs=[];
var imagesOK=0;
var imgs=[];
// put the paths to your images in imageURLs[]
imageURLs.push("yourImage1.png");
imageURLs.push("yourImage2.png");
imageURLs.push("yourImage3.png");
imageURLs.push("yourImage4.png");
imageURLs.push("yourImage5.png");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.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 imgs[] array holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
// for example, draw the images on the canvas
var nextX=10;
for(var i=0;i<imgs.length;i++){
context.drawImage(imgs[i],nextX,10);
nextX+=imgs[i].width;
}
}

Related

Pre-loading images with Javascript | Not Working

I have a masonry grid where the images are black and white and when you hover over them, the color images appear. They are not composite images. They are all separate. (I'm just sorting out bugs for someone else's code)
On initial hover after a fresh page load, there is a delay (and grey overlay) when hovering over. After the initial, it's of course instantaneous when it switches to the color photo.
So what I'm trying to do is pre load the images with some javascript, but I'm having trouble doing this. Below is what I have for code. Also, this is in Wordpress. Not sure if that matters.
All of the images are background images too, not hardcoded into the html. It's all background css. Thanks for any help!
<script language="JavaScript">
$('document').ready(function preloader() {
// counter
var i = 0;
// create object
imageObj = new Image();
// set image list
images = new Array();
images[0]="images/treatment_locations.jpg"
images[1]="images/community_news_events.jpg"
images[2]="images/success_stories.jpg"
images[3]="images/self_assessment.jpg"
images[4]="images/our_associates.jpg"
images[5]="images/treatment_programs.jpg"
images[6]="images/patient_portal.jpg"
images[7]="images/FAQ.jpg"
images[8]="images/what_to_expect.jpg"
// start preloading
for(i=0; i<=8; i++)
{
imageObj.src=images[i];
}
});
</script>
If you overwrite the src in each iteration, you're not giving the browser a chance to fetch the image. You probably only preload the last image.
Try:
var imageObjs = [];
$('document').ready(function preloader() {
// counter
var i = 0;
// set image list
images = new Array();
images[0]="images/treatment_locations.jpg"
images[1]="images/community_news_events.jpg"
images[2]="images/success_stories.jpg"
images[3]="images/self_assessment.jpg"
images[4]="images/our_associates.jpg"
images[5]="images/treatment_programs.jpg"
images[6]="images/patient_portal.jpg"
images[7]="images/FAQ.jpg"
images[8]="images/what_to_expect.jpg"
// start preloading
for(i=0; i<=8; i++)
{
var imageObj = new Image();
imageObj.src=images[i];
imageObjs.push(imageObj);
}
});
That's another aproach, where it stores only the images that were successfully loaded.
var imgObjs = [];
$(document).ready(function preloader() {
// images list
var images = [
'treatment_locations.jpg',
'community_news_events.jpg',
'success_stories.jpg',
'self_assessment.jpg',
'our_associates.jpg',
'treatment_programs.jpg',
'patient_portal.jpg',
'FAQ.jpg',
'what_to_expect.jpg'
];
for (var i in images) {
var img = new Image();
img.src = 'images/' + images[i];
// stores it on array after loading
img.onload = function() {
imgObjs.push(this);
};
}
});

How to get click event on images which is placed on canvas

I have create program to display multiple images on canvas. Now I want to get that images data using mouse click event which is placed on canvas.
My JavaScript cod is -
var canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
canvas.width = 720;
canvas.height = 480;
//I got images data in one array
var imageobj = new Array();
for (var d=0;d<calloutImageArray.length;d++)
{
imageobj[d] = new Image();
(function(d)
imageobj[d].src = sitePath+"ATOM/chapter1/book/"+calloutImageArray[d];
imageobj[d].onload = function()
{
ctx.drawImage(imageobj[d], calloutImageArrayX[d], calloutImageArrayY[d],calloutImageArrayW[d], calloutImageArrayH[d]);
};
})(d);
}
Fairly easily done:
Listen for mousedown events using canvas.addEventListener
On mousedown, check if the mouse is inside any image.
Get the image data for the image under the mouse.
Example code:
function handleMousedown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// get the mouse position
var mouseX=e.clientX-BBoffsetX;
var mouseY=e.clientY-BBoffsetY;
// loop through each image and see if mouse is under
var hit=-1;
for(var i=0;i<imageobj.length;i++){
var x=calloutImageArrayX[i];
var y=calloutImageArrayY[i];
var w=calloutImageArrayW[i];
var h=calloutImageArrayH[i];
if(mouseX>=x && mouseX<=x+w && mouseY>=y && mouseY<=y+h){
hit=i;
}
}
// you clicked the image with index==hit
// so get its image data
if(hit>=0){
var imageData=ctx.getImageData(
calloutImageArrayX[hit],
calloutImageArrayY[hit],
calloutImageArrayW[hit],
calloutImageArrayH[hit]);
// now do your thing with the imageData!
}
}
Example code and a Demo:
var $results=document.getElementById('results');
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var BB,BBoffsetX,BBoffsetY;
function setBB(){
BB=canvas.getBoundingClientRect();
BBoffsetX=BB.left;
BBoffsetY=BB.top;
}
setBB();
window.onscroll=function(e){ setBB(); }
var imageobj=[];
var calloutImageArrayX=[10,125,10,125];
var calloutImageArrayY=[10,10,150,150];
var calloutImageArrayW=[];
var calloutImageArrayH=[];
// put the paths to your images in imageURLs[]
var imageURLs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/character3.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/character2.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/character1.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stack1/avatar.png");
// the loaded images will be placed in imageobj[]
var imagesOK=0;
startLoadingAllImages(imagesAreNowLoaded);
// Create a new Image() for each item in imageURLs[]
// When all images are loaded, run the callback (==imagesAreNowLoaded)
function startLoadingAllImages(callback){
// iterate through the imageURLs array and create new images for each
for (var i=0; i<imageURLs.length; i++) {
// create a new image an push it into the imageobj[] array
var img = new Image();
img.crossOrigin='anonymous';
// Important! By pushing (saving) this img into imageobj[],
// we make sure the img variable is free to
// take on the next value in the loop.
imageobj.push(img);
// when this image loads, call this img.onload
img.onload = function(){
// this img loaded, increment the image counter
imagesOK++;
// if we've loaded all images, call the callback
if (imagesOK>=imageURLs.length ) {
callback();
}
};
// notify if there's an error
img.onerror=function(){alert("image load failed");}
// set img properties
img.src = imageURLs[i];
}
}
// All the images are now loaded
// Do drawImage & fillText
function imagesAreNowLoaded(){
// the imageobj[] array now holds fully loaded images
// the imageobj[] are in the same order as imageURLs[]
// add widths & heights to the appropriate arrays
for(var i=0;i<imageobj.length;i++){
calloutImageArrayW.push(imageobj[i].width);
calloutImageArrayH.push(imageobj[i].height);
}
// listen for mousedown events
canvas.onmousedown=handleMousedown;
draw();
}
function draw(){
ctx.clearRect(0,0,cw,ch);
for(var d=0;d<imageobj.length;d++){
ctx.drawImage(imageobj[d],
calloutImageArrayX[d], calloutImageArrayY[d],
calloutImageArrayW[d], calloutImageArrayH[d]);
}
}
function handleMousedown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// get the mouse position
var mouseX=e.clientX-BBoffsetX;
var mouseY=e.clientY-BBoffsetY;
// loop through each image and see if mouse is under
var hit=-1;
for(var i=0;i<imageobj.length;i++){
var x=calloutImageArrayX[i];
var y=calloutImageArrayY[i];
var w=calloutImageArrayW[i];
var h=calloutImageArrayH[i];
if(mouseX>=x && mouseX<=x+w && mouseY>=y && mouseY<=y+h){
hit=i;
}
}
// you clicked the image with index==hit
// so get its image data
if(hit>=0){
var imageData=ctx.getImageData(
calloutImageArrayX[hit],
calloutImageArrayY[hit],
calloutImageArrayW[hit],
calloutImageArrayH[hit]);
var pos;
switch(hit){
case 0:pos='top-left';break;
case 1:pos='top-right';break;
case 2:pos='bottom-left';break;
case 3:pos='bottomRight';break;
}
$results.innerHTML='You clicked the '+pos+' image.<br>This imageData has this length: '+imageData.data.length;
}
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<h4 id="results">Click on an image</h4>
<canvas id="canvas" width=300 height=300></canvas>
Take my advice and go with something like fabricJS , it will make your life very easy. In that you can easily have multiple objects on the canvas and also perform functions (Scale,rotate,pan) on them separately.

Are there any alternatives for using toDataURL in Chrome?

The main problem is that I have to work with many images. And I can't use crossOrigin Attribute for all of them.
My code looks like this:
<script>
var c=document.getElementById('example');
var ctx=c.getContext('2d');
var LeftHand = new Image();
LeftHand.id="imq1";
var RightHand = new Image();
RightHand.id="imq2";
var Body = new Image();
Body.id="imq6";
boyBody.src = "https://getout-s3.s3.amazonaws.com/baseBody/boy-02.png";
LeftHand.src = "https://getout-s3.s3.amazonaws.com/NK4XtQvkZ4MGctZf_.hand(unisex)_13.png ";
RightHand.src = "https://getout-s3.s3.amazonaws.com/OPdFPcU2sORgNmTy_.hand(unisex)_9.png ";
Body.src = "https://getout-s3.s3.amazonaws.com/HRZqrTYSdJXGedgX_.Body_(m)7.png ";
boyBody.onload = function() {
ctx.drawImage(boyBody, 0, 0, boyBody.width/2, boyBody.height/2);
ctx.drawImage(LeftHand, (899 - LeftHand.width/2)/2, (867 - LeftHand.height/2)/2, LeftHand.width/2, LeftHand.height/2);
ctx.drawImage(Underwear, (599 - Underwear.width/2)/2, (845 - Underwear.height/2)/2, Underwear.width/2, Underwear.height/2);
ctx.drawImage(Body, (599 - Body.width/2)/2, (557 - Body.height/2)/2, Body.width/2, Body.height/2);
var img = c.toDataURL("image/png");
document.write('<img src="' + img + '" />');
};
</script>
Browsers don't let programmers export cross-domain content for very good security reasons. Your private banking info is cross-domain content that you don't want give to thieves using the canvas as an export device.
Therefore, context.toDataURL is disabled immediately after you drawImage a cross-domain image onto canvas. The same disabling is true for context.getImageData. (context.getImageData is another way to export canvas content).
To allow exporting the canvas content to your users, you will have to host all the images on the same domain as your webpage.
BTW, you must give all your elements time to load before drawing them. Here's an image loader that loads all your images in advance and then calls start() when all the images are fully loaded. Put your ctx.drawImage's in start().
// put the paths to your images in imageURLs[]
var imageURLs=[];
imageURLs.push("https://getout-s3.s3.amazonaws.com/baseBody/boy-02.png");
imageURLs.push("https://getout-s3.s3.amazonaws.com/NK4XtQvkZ4MGctZf_.hand(unisex)_13.png");
// ...etc, for all images
// the loaded images will be placed in imgs[]
var imgs=[];
var imagesOK=0;
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.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 imgs[] array now holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
}

Two different image onLoad

Currently I only have one image onLoad everytime when i run my animation.
var imgFish = new Image();
imgFish.onload = init;
imgFish.src = 'Image';
I'm try to make two or more different image to load at the same time.
I have only one orange fish moving on the canvas when i press on the 'Add a fish!' button. I want to make more different fish swimming on the canvas too. I have created another button called 'Add a different color fish!', I want to add a fish but with a different image with the same code to allow the fish to animation on the canvas.
Anyone knows how can i achieve it?
see http://jsfiddle.net/qx3tq5bL/1/
Your code requires a image object to create a new fish in the constructor of Fish. Thus you need to do 2 things:
First, Create a new image object pointing to a different image of a fish of different color
var imgFish2 = new Image();
imgFish2.onload = init;
imgFish2.src = 'https://dl.dropboxusercontent.com/s/0q7o0i23xmz719m/FishStrip.png';
Second, Bind function to your new button in function init:
document.getElementById("button1").onclick = function() {
// create another fish using the Fish class
var anotherFish = new Fish(xPos, yPos, speedX, speedY, imgFish2, frameWidth, frameHeight);
// put this new fish into the fishes[] array
fishes.push(anotherFish) ;
// make it start changing directions
anotherFish.changeDirection();
// draw this new fish
anotherFish.drawFish();
}
Here's a generic image loader that preloads all your images and then calls start()
// image loader
// put the paths to your images in imageURLs[]
var imageURLs=[];
// push all your image urls!
imageURLs.push("");
// the loaded images will be placed in images[]
var imgs=[];
var imagesOK=0;
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.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 imgs[] array now holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
}

KineticJS Multiple Images

I got a strange problem with KineticJS.
I'm trying to load multiple Images and simply draw them on Canvas.
JSFiddle is here:
http://jsfiddle.net/riyuk/DbHuV/
The weird thing is, that Kinetic only loads one Image (always the last one in the array).
If I uncomment the Code and do the same with Kinetic.Rect everything works fine.
var obj = new Kinetic.Rect({
x: opts.x,
y: opts.y,
width: opts.width,
height: opts.height,
fill: 'green',
stroke: 'black',
strokeWidth: 4
});
cb(obj);
Any - working - suggestions?
Greetings
Here's an alternate image loader:
This loads all images that were pushed into the imageURLs array.
After all images are fully loaded, the start() function is called.
In start, the imgs[] array holds the images in the same order as imageURLs[]
// image loader
var imageURLs=[];
var imagesOK=0;
var imgs=[];
imageURLs.push("");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.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 imgs[] array holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
}

Categories

Resources