【问题标题】:jQuery: new image added to DOM always has width 0 after loadedjQuery:添加到 DOM 的新图像在加载后总是宽度为 0
【发布时间】:2011-05-21 22:28:22
【问题描述】:

我需要使用动态创建的图像标签来获取图像的尺寸。有用。但仅使用 attr('width') 并且仅当我不将图像添加到 DOM 时。否则,返回的尺寸为零。为什么? :)

this.img = $('<img/>', {'src': e.url} );           // generate image
this.img.appendTo('body');                         // add to DOM
this.img.load(function(self){return function(){    // when loaded call function
    console.log(self.img.attr('src'));
    console.log(self.img.attr('width'));
    console.log(self.img.width());
    console.log(self.img.css('width'));
}; }(this) );                                      // pass object via closure

所以我生成图像,将其添加到 DOM 并定义一个处理函数,以便在加载图像时调用。我正在使用闭包向它传递对原始对象的引用,在闭包中称为“self”。我正在转储图像的 URL 以确保引用是正确的。输出是:

pic.jpg
0
0
0px

现在这是 奇怪 的事情:如果我删除上面的第二行(appendTo),那么它会突然起作用,但仅适用于 attr('width'):

pic.jpg
1024
0
0px

这种行为对我来说没有任何意义。我希望在上述所有六种情况下都能获得实际的图像尺寸。我现在知道如何解决这个问题,但我想了解它为什么会发生。它是一个错误吗?还是有什么合乎逻辑的原因?

以上结果适用于 Safari。我刚刚使用 Chrome 进行了测试,在第一个示例中我得到了所有正确的值,但在第二个示例中仍然是两个零。很奇怪。

【问题讨论】:

  • 你确定你总是有一个有效的 e.url 吗??
  • @travel boy 你能不能给这个变量取个别的名字来代替 img this.img , this.newImgSource 等等...///
  • @travelboy & gov:同意,保存图像的 jQuery 对象的属性应该更改为 img 是一个标签名称,只是一个好习惯。
  • @gov:我将 img 重命名为 ximg 并没有改变任何东西。是的,e.url 是有效的,并且在所有测试中都是相同的。
  • @travelboy 我们可以做我下面建议的例子吗//只是为了一一消除。

标签: javascript jquery css image dimensions


【解决方案1】:

我为 Safari 找到了一个可靠的解决方案:

  • 创建图像
  • 附加 load() 处理程序
  • 仅在此之后,设置src 属性!!

我仍然不明白为什么 width 应该返回零,但是如果您仅在设置 src 之后附加负载处理程序,似乎会发生意想不到的事情。我之所以有这个想法,只是因为我遇到了 IE 的另一个问题(它甚至没有调用加载处理程序,因为它认为在附加处理程序之前加载了图像),所以我学到的教训是始终在上述顺序。

【讨论】:

    【解决方案2】:

    在 firebug 和 chrome 中尝试了您的代码,它的行为符合预期:

    var src = 'http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif';
    
    this.img = $('<img/>', { 'src': src } );
    this.img.appendTo('body');                         // add to DOM
    this.img.load(function(self){return function(){    // when loaded call function
        console.log(self.img.attr('src'));
        console.log(self.img.attr('width'));
        console.log(self.img.width());
        console.log(self.img.css('width'));
     }; }(this) ); 
    

    得到以下内容:

    http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif
    215
    215
    215px
    

    删除 appendTo() 行后,我可以在 Chrome 中重现该行为,但我并不觉得这很奇怪。 width() 正在计算“显示”元素的实际宽度 - 例如每次你把图像放在一个隐藏的 div 中,它都会是 == 0 !

    尝试用以下内容替换 appendTo 行,你会得到相同的结果:

    this.img.appendTo( $('&lt;div/&gt;').css('display', 'none') );

    更新:

    Safari 3.1.2 的结果在附加到 DOM 时对我来说与 Chrome 完全相同。

    当 img 没有插入到 DOM 中时,我也得到了可以接受(没有奇怪)的结果:

    http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif
    215
    0
    0px
    

    我确信您的设置一定有一些独特的东西......或者它是一个 Safari @Mac OSX 错误(在 Windows env 上尝试过 Safari)。

    【讨论】:

    • 奇怪的是另外一件事:在 Safari 中,当图像附加到 DOM 时,图像的宽度为零。当我不将它附加到 DOM 时,我只能读取它的宽度。你应该觉得这很奇怪!诚然,Chrome 是可以理解的。 Safari 不是。
    • @travelboy 我已经更新了我的答案 - 我真的很想看到 Safari 中的奇怪行为,但对我来说它工作得非常正确......正如您的 Safari 设置中提到的@gov 波纹管img 可能由于某种原因被隐藏了。
    【解决方案3】:

    在我看来,您分配 jQuery 对象然后在图像上调用 load 函数的方式有点过头了,这使得很难理解为什么 jQuery 可能会这样。

    试试这个:

    this.img = $('<img />').attr('src', e.url).appendTo('body');
    console.log('width: ' + this.img.width());
    

    在图像被注入到 DOM 后,我可以完美地得到它。

    你也可以试试这个:

    this.img = $('<img />').attr('src', e.url).css({
       'width': 'auto',
       'height': 'auto'
    }).appendTo('body');
    console.log('width: ' + this.img.width());
    console.log('height: ' + this.img.height());
    

    【讨论】:

    • @Dale:除非图像已经在缓存中,否则您的方法肯定会失败(因为将在加载图像之前读取尺寸)。所以不能这样做——你需要加载函数。
    • 我同意 travelboy , load 确保图像加载到浏览器
    • @travelboy ,您的代码看起来很完美,元素给出 0 的唯一其他原因是如果它们由于某种原因被隐藏,您的图像父容器是否隐藏了??
    • @travelboy ,你在吗?如果可以,我们可以做一些示例,创建一个单独的 div 占位符并将您的图像附加到 div 并执行相同的代码/// 我认为当它附加到 body 时有问题,我们可以开始调试,
    • @gov:img 被添加到 body 的顶层(就在
    【解决方案4】:

    我不认为你的关闭按你想要的方式工作。您是否尝试过类似的方法:

    this.img.load(function(){                          // when loaded call function
        console.log(this.attr('src'));
        console.log(this.attr('width'));
        console.log(this.width());
        console.log(this.css('width'));
    }); 
    

    【讨论】:

    • 我不能这样做,因为我需要引用包含 img 的对象。但是闭包有效(因为我可以访问 img 和对象的其他属性)
    猜你喜欢
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2014-10-02
    • 2016-03-04
    • 2014-02-12
    • 2013-09-26
    • 2014-09-24
    • 2011-07-04
    相关资源
    最近更新 更多