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[]
}
Related
I have created Circle using arc like following way.
var startAngle = 0;
var arc = Math.PI / 6;
var ctx;
var leftValue=275;
var topValue=300;
var wheelImg = ["http://i.stack.imgur.com/wwXlF.png","http://i.stack.imgur.com/wwXlF.png","cat.png","cock.png",
"croco.png","dog.png","eagle.png","elephant.png","lion.png",
"monkey.png","rabbit.png","sheep.png"];
function drawWheelImg()
{
var canvas = document.getElementById("canvas");
if(canvas.getContext)
{
var outsideRadius = 260;
var textRadius = 217;
var insideRadius = 202;
ctx = canvas.getContext("2d");
for(var i = 0; i < 12; i++)
{
var angle = startAngle + i * arc;
ctx.beginPath();
ctx.arc(leftValue, topValue, outsideRadius, angle, angle + arc, false);
ctx.arc(leftValue, topValue, insideRadius, angle + arc, angle, true);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.arc(leftValue, topValue, outsideRadius, angle, angle + arc, false);
ctx.shadowBlur=3;
ctx.shadowColor="#A47C15";
ctx.stroke();
ctx.closePath();
ctx.save();
ctx.translate(leftValue + Math.cos(angle + arc / 2) * textRadius,
topValue + Math.sin(angle + arc / 2) * textRadius);
ctx.rotate(angle + arc / 2 + Math.PI / 2);
var img = new Image();
img.src = wheelImg[i];
ctx.drawImage(img,-44, -25,50,40);
ctx.restore();
}
}
}
function spin()
{
drawWheelImg();
}
drawWheelImg();
<button class="btnSpin" onclick="spin();">Spin</button>
<canvas id="canvas" width="550" height="580"></canvas>
Problem is that it will not load when first page load. But when i click on spin button it will load all images.
Don't know what is the issue. Any help is greatly appreciated.
Note: Here in the question same issue is solve by img.onload function but that for only single image. If there is number of multiple images in array then it's not working.
You want to preload the images.
To do this you can start the loading at the bottom of the page just before the closing </dody> tag.
<script>
// an array of image URLs
var imageNames = ["image1.png", "image2.jpg", ...moreImageNames];
// an array of images
var images = [];
// for each image name create the image and put it into the images array
imageNames.forEach(function(name){
image = new Image(); // create image
image.src = name; // set the src
images.push(image); // push it onto the image array
});
</script>
In the code that uses the images you just need to check if they have loaded yet. To do this just check the image complete attribute.
// draw the first image in the array
if(images[0].complete){ // has it loaded
ctx.drawImage(images[0],0,0); // yes so draw it
}
Note that complete does not mean loaded. If you proved a bad URL or there is another error the complete flag will still be true. Complete means the browser has finished dealing with the image. You will have to add an onload event if there is a chance that images may fail.
Handling Errors
If you are unsure that an image will not load you will have to devise a strategy to deal with the missing content. You will need to answer questions like, Can my app function without the image? Are there alternative sources to get the image from? Is there a way to determine how often this is likely to happen? How do I stop this from happening?
On the simplest level you can flag an image as loaded by adding your own semaphore to the image object during the onload event
// an array of image URLs
var imageNames = ["image1.png", "image2.jpg", ...moreImageNames];
// an array of images
var images = [];
// function to flag image as loaded
function loaded(){
this.loaded = true;
}
// for each image name create the image and put it into the images array
imageNames.forEach(function(name){
image = new Image(); // create image
image.src = name; // set the src
image.onload = loaded; // add the image on load event
images.push(image); // push it onto the image array
});
Then in code you will check for the loaded semaphore before using the image.
// draw the first image in the array
if(images[0].loaded){ // has it loaded
ctx.drawImage(images[0],0,0); // yes so draw it
}
Critical content
If you have images that are required for you app to function then you should redirect to an error page if there is a problem loading the image. You may have several servers so you can also try the different sources before giving up.
If you need to stop the app or try an alternative URL you will have to intercept the onerror image event.
To simplify your use of the images (100% sure the images are loaded when that app runs) you should start the parts that use the images only when all the images are loaded. One way to do this is to count all the images that are being loaded, and count down as the images load. When the counter reaches zero you know all the images have loaded and you can then call you app.
The following will load images, if they fail it will try another server (source) until there are no more options at which point you should redirect to the appropriate error page to inform the client that a monkey has put a spanner in the works. It counts the loading images and when all the images have loaded then it will start the app running, sure in the knowledge that all the image content is safe to use.
// Server list in order of preferance
var servers = ["https://fakesiteABC.com/", "http://boogusplace.com/", "http://foobarpoo.com.au/"];
// an array of image URLs
var imageNames = ["image1.png", "image2.jpg", ...moreImageNames];
// an array of images
var images = [];
// loading count tracks the number of images that are being loaded
var loadingImageCount = 0;
// function to track loaded images
function loaded(){
loadingImageCount -= 1;
if(loadingImageCount === 0){
// call your application start all images have loaded
appStart();
}
}
// function to deal with error
function loadError(){ // the keyword "this" references the image that generated the event.
if(this.retry === undefined){ // is this the first error
this.retry = 1; // point to the second server
}else{
this.retry += 1; // on each error keep trying servers (locations)
}
// are the any other sources to try?
if(this.retry >= servers.length){ // no 11
// redirect to error page.
return;
}
// try a new server by setting the source and stripping the
// last server name from the previous src URL
this.src = servers[this.retry] + this.src.replace( servers[ this.retry - 1],"");
// now wait for load or error
}
// for each image name create the image and put it into the images array
imageNames.forEach(function(name){
image = new Image(); // create image
image.src = servers[0] + name; // set the src from the first server
image.onload = loaded; // add the image on load event
image.onerror = loadError; // add the image error handler
images.push(image); // push it onto the image array
loadingImageCount += 1; // count the images being loaded.
});
There are many other strategies for dealing with missing content. This just shows some of the mechanism used and does not define a perfect solution (there is none)
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);
};
}
});
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[]
}
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;
}
}
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[]
}