简体   繁体   中英

Detecting orientation of images with Javascript

I'm trying to find a way to detect the orientation of images (landscape or portrait).

The HTML simply contains a few img tags with source already filled in. The script should then detect the orientation and add the images to dynamically created divs acting as thumbnails.

The script I've been using is this (found it on here somewhere)

    for (i = 0; i < pics.length; i++) {
      pics[i].addEventListener("load", function() {
        if (this.naturalHeight > this.naturalWidth) {
          this.classList.add("portrait")
        } else {
          this.classList.add("landscape")
        }
     })
    }

Now this usually works fine when first loading the page. When refreshing however, it behaves erratically, adding the right class to some images and not adding any class at all to others.

I also tried this

for (i = 0; i < pics.length; i++) {
  var img = pics[i];
  var width = img.naturalWidth;
  var height = img.naturalHeight;
  if (height > width) {
    img.classList.add("portrait")
  } else {
    img.classList.add("landscape")
  }
}

Which also works unpredictably. All images get a class added to them, but some get the wrong one.

I'm guessing the problems might come from the images not completely loading before the script runs and thus the script not being able to measure them correctly, but I'm not sure. Anyhow, I don't really know how to fix it either.

To give an idea of what I'm going for, here's a link to the page: http://pieterwouters.tumblr.com/

Any ideas much appreciated.

If the image is already loaded when you call pic.addEventListener("load", ...) , the load event handler will not be triggered. You should call it if pic.complete is true, as suggested in this answer .

 var pics = document.querySelectorAll("img"); var pic; for (i = 0; i < pics.length; i++) { pic = pics[i]; if (pic.complete) { // The image is already loaded, call handler checkImage(pic); } else { // The image is not loaded yet, set load event handler pic.addEventListener("load", function() { checkImage(this); }) } } function checkImage(img) { if (img.naturalHeight > img.naturalWidth) { img.classList.add("portrait") } else { img.classList.add("landscape") } } 
 img { border: 1px solid; } .landscape { border-color: red; } .portrait { border-color: blue; } 
 <img src="//placehold.it/50x100"> <img src="//placehold.it/200x100"> 

Thanks to Ricky. I borrowed the image links and the style attributes from his answer.

For a safer but more expensive approach you could duplicate the images in memory and add the corresponding class.

 const images = [...document.querySelectorAll('img')].map(el => { return new Promise((resolve, reject) => { let img = new Image(); img.addEventListener('load', function() { const { naturalHeight, naturalWidth } = img; if (naturalHeight > naturalWidth) el.classList.add("portrait"); else el.classList.add("landscape"); img = null; //GC resolve(); }); img.src = el.src; }); }); 
 img { border: 1px solid; } .landscape { border-color: red; } .portrait { border-color: blue; } 
 <img src="//placehold.it/50"> <img src="//placehold.it/50x100"> <img src="//placehold.it/200x100"> <img src="//placehold.it/50x60"> <img src="//placehold.it/10x30"> <img src="//placehold.it/50x20"> 

Thanks for the help!

ConnorsFan, based on your earlier comment I added a part to take into account already loaded images and came up with this

// forgot to mention this part in my original post
var pics = document.getElementsByTagName("img");

for (i = 0; i < pics.length; i++) {
    pics[i].addEventListener("load", function() {
        if (this.naturalHeight > this.naturalWidth) {
            this.classList.add("portrait")
        } else {
            this.classList.add("landscape")
        }
     })  
     if (pics[i].complete) {
         if (pics[i].naturalHeight > pics[i].naturalWidth) {
             pics[i].classList.add("portrait")
         } else {
             pics[i].classList.add("landscape")
         }
     }
 }

Which works, your solution seems a bit more elegant though so I'll probably use that one.

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