Multiple images not loading onto canvas

I created a Circle using an arc as the next path.

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> 

The problem is that it will not load when the first page loads. But when I press the rotation button, it loads all the images.

I don’t know what the problem is. Any help is appreciated.

Note: Here, in the question , the same problem is solved by img.onload , but only for one image. If there are several images in the array, this does not work.

+5
source share
1 answer

You want to preload the images.

To do this, you can start the download at the bottom of the page immediately before the closing </dody> .

 <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 code that uses images, you just need to check if they are still loaded. To do this, simply check the 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 loading. If you find a bad URL or there is another mistake, then the full flag will still be right. Finish means that the browser has finished working with the image. You will need to add the onload if there is a possibility that the images may fail.

Error processing

If you are not sure that the image will not load, you will have to develop a strategy to combat the missing content. You will need to answer questions such as: can my application work without an image? Are there any alternative sources for image acquisition? Is there a way to determine how often this can happen? How to stop this?

At the simplest level, you can mark an image as loaded by adding your own semaphore to the image object during the onload

  // 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 the code you will check 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 the images necessary for your application to function, you should be redirected to the error page if there is a problem loading the image. You may have multiple servers, so you can try different sources before giving up.

If you need to stop the application or try an alternative URL, you will have to catch the onerror event.

To simplify the use of images (100% sure that images are loaded when this application starts), you should run parts that use images only when loading all images. One way to do this is to count all downloaded images and the countdown when loading images. When the counter reaches zero, you know that all the images are uploaded, and then you can call the application.

The following files will be downloaded, if they fail, it will try another server (source) until there are more parameters, at this point you should redirect errors to the corresponding page to inform the client that the monkey put the wrench in work. It counts boot images and downloads all images, and then launches an application that is sure that all the contents of the image are 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 to deal with missing content. It just shows some kind of mechanism used and does not determine the ideal solution (it is not)

+1
source

Source: https://habr.com/ru/post/1239818/


All Articles