简体   繁体   中英

How to dynamically change images on a webpage?

Problem: The previously loaded images have to be changed dynamically when a new image is downloaded and detected by image.onload event. Say, picture1.png downloaded and immediately changed, picture2.png downloaded and immediately changed and so on. I have tried it as below, but it didn't work:

<script type="text/javascript">
 loadImage = function(){    
     var imgs = new Array();    
     var IMG = document.getElementsByTagName('img');    
     for(var i=1;i<=IMG.length;i++)
     {
       imgs[i] = new Image();
       imgs[i].src = "picture" + i + ".png";
       imgs[i].onload = function(){
         alert('picture'+i+' loaded');
         IMG[i].setAttribute('src',imgs[i].getAttribute('src'));
       }           
     }              
 }    
</script>    
 <img src="sample.png" />
 <img src="sample.png" />
 <img src="sample.png" />
 <img src="sample.png" />
 <input type="button" value="Load Image" onclick="loadImage()"> 

How things will happen in the desired manner?

Because variables declared with the var keyword is function scoped and the onload function executes after the loop has finished variable i will not equal the value of i in that iteration when executing.

Replace your onload function with this code instead. It will create a new function scope.

imgs[i].onload = function(index) {
  return function(index) {
    alert('picture' + index + ' loaded');
    IMG[index].setAttribute('src', imgs[index].getAttribute('src'));
  }
}(i)

I would also change you're code to not loading the image twice.

function loadImage() {
  var images = document.getElementsByTagName('img');
  for (var i = 0; i <= images.length; i++) {
    var newImg = new Image();
    newImg.src = "http://dummyimage.com/150/000/fff&text=Image" + i;
    newImg.onload = function(index, newImg) {
      return function() {
        var img = images[index];
        img.parentNode.replaceChild(newImg, img);
      }
    }(i, newImg)
  }
}

If I understood your question correctly, you want to change the placeholder images as soon as the new images are completely loaded. By just passing the src attribute you rely on caching but the method below, although untested, should do the replacing in place. The i is kind of like a pointer which holds the growing value, so you can't use it as a reference in event callbacks.

 function loadImage() { var imgs = document.querySelectorAll("img"); for (var i = 0; i < imgs.length; i++) { var newImg = new Image(); newImg.src = "picture" + i + ".png"; newImg.onload = function(img) { // Construct a callback for this <img> return function() { img.parentNode.replaceChild(newImg, img); } }(imgs[i]); } } 

Edit : as said, I previously introduced another scoping issue in my code when fixing the original one. This is now fixed with a callback constructor function.

From this answer,

Well, the problem is that the variable i, within each of your anonymous functions, is bound to the same variable outside of the function.

What you want to do is bind the variable within each function to a separate, unchanging value outside of the function:

So your code should look somewhat like this :

 <script type="text/javascript"> var IMG = document.getElementsByTagName('img'); var imgs = new Array(); loadImage = function(){ for(var i=0;i<IMG.length;i++) { imgs[i] = new Image(); imgs[i].src = "http://dummyimage.com/150/000/fff&text=Image"+i; imgs[i].onload = onloaded(i); } } function onloaded(i) { IMG[i].setAttribute('src',imgs[i].getAttribute('src')); } </script> <img src="http://placehold.it/150" /> <img src="http://placehold.it/150" /> <img src="http://placehold.it/150" /> <img src="http://placehold.it/150" /> <input type="button" value="Load Image" onclick="loadImage()"> 

Note : array index of IMG starts with 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM