使用Javascript检测图像方向

3
我正在寻找一种检测图像方向(横向或纵向)的方法。 HTML 中已经包含了带有源的几个 img 标签。然后,脚本应该检测方向并将图像添加到动态创建的 div,充当缩略图。我一直在使用以下脚本(在这里找到的):
    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")
        }
     })
    }

通常情况下,在首次加载页面时,这通常是有效的。但是在刷新时,它会表现不稳定,对某些图像添加正确的类,而对其他图像则不添加任何类。

我也尝试了这个方法

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")
  }
}

这个也表现得不可预测。所有的图片都被添加了一个类,但是有些却被添加了错误的类。

我猜问题可能来自于脚本在图片完全加载之前运行,因此无法正确地测量它们,但是我不确定。无论如何,我也不知道如何修复它。

为了让你了解我的想法,这里有一个链接到页面的链接:http://pieterwouters.tumblr.com/

非常感谢任何想法。


你的脚本是在页面顶部还是底部? - inarilo
这个脚本应该在页面加载完成后执行。现在你怎么执行它? - Mr Zach
它位于页面底部,或者至少在Tumblr允许的范围内(因为它会添加一些自己的自动脚本),因此理论上图像应该在脚本之前加载。 - Pieter Wouters
3个回答

3

如果你在调用pic.addEventListener("load", ...)时,图片已经加载完成,则不会触发载入事件处理器。如此答案所建议的一样,当pic.complete为真时应该调用它。

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">

感谢 Ricky 的帮助,我从他的答案中借用了图像链接和样式属性。

2

为了更安全但更昂贵的方法,您可以在内存中复制图像并添加相应的类。

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">


0

感谢您的帮助!

根据您之前的评论,我添加了一个部分来考虑已加载的图像,并得出了以下结果。

// 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")
         }
     }
 }

都可以,不过你的解决方案更优雅,所以我可能会用那个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接