首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >img naturalWidth意外返回值

img naturalWidth意外返回值
EN

Stack Overflow用户
提问于 2021-04-25 04:49:29
回答 1查看 214关注 0票数 2

我有一个有反应的图像:

代码语言:javascript
复制
<img 
    class="post-card-image" 
    srcset="/content/images/size/w300/2021/04/photo-1459411552884-841db9b3cc2a.jpeg 300w,
           /content/images/size/w600/2021/04/photo-1459411552884-841db9b3cc2a.jpeg 600w,
           /content/images/size/w1000/2021/04/photo-1459411552884-841db9b3cc2a.jpeg 1000w,
           /content/images/size/w2000/2021/04/photo-1459411552884-841db9b3cc2a.jpeg 2000w"
   sizes="(min-width: 1200px) 600px, (min-width: 768px) 50vw, 100vw" 
   src="/content/images/size/w600/2021/04/photo-1459411552884-841db9b3cc2a.jpeg"
   alt="Publishing options"
   loading="lazy" />

在火狐上模拟iPhone X (375x812 DPR:3)时,我可以看到通过检查img.currentSrc加载了2000 w图像。

我的问题是,当我检查img.naturalWith时,它给出了375值,它正是100vw。我原以为这会返回图像的原始宽度20002000/3 = 666

我的问题是,为什么img.naturalWith在这种特殊情况下返回值375

编辑

这是一个问题的演示

代码语言:javascript
复制
const img1 = document.getElementById("img-with-srcset");
const img2 = document.getElementById("img-no-srcset");

window.addEventListener('load', (event) => {
  console.log('page is fully loaded');
  
  console.log("img1.naturalWidth : ", img1.naturalWidth);
  console.log("img1.currentSrc : ", img1.currentSrc);
  document.getElementById('meta-1').innerHTML = `Natural Width: ${img1.naturalWidth}<br/>Current src : ${img1.currentSrc}`;

  console.log("img2.naturalWidth : ", img2.naturalWidth);
  console.log("img2.currentSrc : ",img2.currentSrc);
  document.getElementById('meta-2').innerHTML = `Natural Width: ${img2.naturalWidth}<br/>Current src : ${img2.currentSrc}`;  
});
代码语言:javascript
复制
.grid {
  display: grid;
  grid-template-columns: 1fr;
  max-width: 1200px;
  margin: 0 auto;
}

@media (min-width: 768px) {
  .grid {
    grid-template-columns: 1fr 1fr;
  }
}

.card-image {
  position: relative;
  width: 100%;
  height: 300px;
}

.card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
代码语言:javascript
复制
<div class="grid">
  <div class="card">
    <div class="card-image">
      <img  id="img-with-srcset"
     srcset="https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=400 400w,
             

https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=600 600w,
                    
https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=800 800w,

https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=2000 2000w" 
sizes="(min-width: 1200px) 600px, (min-width: 768px) 50vw, 100vw" 
src="https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=2000" alt="Writing posts" />  
    </div>  
    <div class="card-meta" id="meta-1"></div>
  </div>
  
  <div class="card">
    <div class="card-image">
      <img  
           id="img-no-srcset"
           src="https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=2000" 
           alt="Writing posts"
       />  
    </div>  
    <div class="card-meta" id="meta-2"></div>
  </div>
</div>

以及在火狐上模拟iPhone X (375x812 DPR:3)时的屏幕截图:

第一个图像有srcsetsizes攻击,第二个图像没有。您可以看到,在这两种情况下,都通过检查w=2000加载了相同的图像( naturalWidth ),但是naturalWidth的值是不同的。对于两个图像,CSS都是相同的。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-27 01:48:33

自然宽度/高度返回图像的固有density-corrected宽度/高度。

我想,对于像JPEG这样的位图图像来说,内在的维度是非常清晰的。

硬比特是“密度校正”的意思。

在内部,当选择图像源时,它有一个https://html.spec.whatwg.org/multipage/images.html#current-pixel-density值。此值确定如下(规格):

  • 如果从图像的src中选择图像源,则为1
  • 如果从srcset属性中选择了图像源,并且它有一个像素密度描述符 (nx),则使用该描述符的值。
  • 如果从srcset属性中选择了图像源,并且它有一个宽度描述符,那么像素密度表示宽度描述符值除以使用的源大小。这个源大小是在sizes属性<source>中定义的。

这是第三种情况。

为了减少它的动态性,让我们在50vw属性中设置一个唯一的sizes值。

代码语言:javascript
复制
const img1 = document.getElementById("img-with-srcset");

window.addEventListener('load', (event) => {
  console.log("img1.naturalWidth : ", img1.naturalWidth);
  console.log("img1.currentSrc : ", img1.currentSrc);
  const src = img1.currentSrc;
  const width_descriptor = src.slice(src.lastIndexOf("w=") + 2);
  // in our case the intrinsic width is the same as width_descriptor
  const intrinsic_width = width_descriptor;
  const source_size = innerWidth * 0.5; // 50vw
  const density = width_descriptor / source_size;
  const expected_size = intrinsic_width / density;
  console.log( "expected : ", expected_size );
});
代码语言:javascript
复制
<img  id="img-with-srcset"
  srcset="https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=400 400w,
    https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=600 600w,
    https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=800 800w,
    https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=2000 2000w" 
  sizes="50vw" 
  src="https://images.unsplash.com/photo-1509587584298-0f3b3a3a1797?w=2000" alt="Writing posts" />

因此,在没有像素密度描述符的情况下,自然宽度/高度值确实取决于所选的size值,该值可以是相对于视图端口的大小。

不知道您愿意做什么,很难更进一步,但是请注意,有个建议公开了当前正在进行的<source>的大小。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67249881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档