最早获得图像宽度的事件

所以我有一些糟糕的JavaScript来将图像居中,如果页面上的超过阈值宽度。 它还检查某些类尚未手动应用。

 $('img,object').bind('load', function() { w = $(this).width(); if (w > 400 && !( $(this).hasClass('inlineimage') | $(this).parent().hasClass('inlineimage') )) $(this).css('margin', '10px ' + (parseInt((800-w)/2)-30) +'px'); }); 

这是可怕的,但这背后的意义原本都很清醒。 CMS不容易指定对齐并开发它以允许这将花费大量时间远离其他作业。 客户端黑客工作。

唯一的问题是JS等待整个图像加载。 显然,这意味着在较慢的网络上,页面加载,图像开始加载,一段时间后图像会卡入到位。 丑陋。

但是一旦开始下载它,浏览器就会知道图像的宽度。 我真的很想加入这个事件,并发现这个视觉错误。

当然,如果有一种CSS方式接近这一点,我也对此持开放态度。

在支持它的浏览器中,您可以轮询自然尺寸:

 var interval = setInterval( function() { if( img.naturalWidth ) { clearInterval(interval); console.log( "Natural available: "+ (new Date - now ); console.log( img.naturalWidth, img.naturalHeight ); } }, 0 ); 

在这个关于未缓存图像的演示中,我得到:

 Natural available: 782 62 71 Loaded: 827 

因此,在加载事件之前50毫秒可以获得真实尺寸。 不幸的是,在IE中,readystate "loading"并不能保证真正的尺寸。

在每次测试之前更改图像的查询字符串以确保未缓存。

以下是关于自然维度的whatwg链接: http : //www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#dom-img-naturalwidth

 var span = document.getElementById('span'); // The parent span var check = function (){ if(span.offsetWidth > 0){ console.log('Width while loading', span.offsetWidth); } else{ setTimeout(check, 100); } }; check(); 

演示 。 这应该在控制台首先加载时显示宽度,然后在加载后显示宽度。 只要图像没有缓存就可以了。 (如果演示对某人不起作用,请尝试将图像URL的hoo部分更改为其他任何内容)

为了这个目的而不仅仅是最新的浏览器,我拼凑了一个尽力而为的蛮力。 它在尝试之间等待500毫秒,并检查图像以查看当前运行的宽度是否与上次尝试的宽度相同。

只要图像的宽度在两个连续的通道中相同,我们就会运行居中代码。

这使用数组来跟踪事物,因此我们不会经常强奸DOM,也不会查询不适用的项目(因为它们已被处理或排除)。


 attempts = 0; arr = []; $.each($('img,object').not('inlineimage'), function(){ arr.push([this, -2, $(this).width()]); }); checkImgs = function() { attempts++; newarr = [] $.each(arr, function(){ if ($(this[0]).parent().hasClass('inlineimage')) return; w = $(this[0]).width(); this[1] = this[2]; this[2] = w; if (this[1] != this[2]) return newarr.push(this); // We know this image is loaded enough now - we can do things! if (w >= 400) $(this[0]).css('margin', '10px ' + (parseInt((800-w)/2)-30) +'px'); }); arr = newarr; if (arr.length && attempts < 6) setTimeout(checkImgs, 500); } setTimeout(checkImgs, 500); 

它并不漂亮,但它似乎有效地工作(CPU受到我之前的一些尝试的打击)并且很快(缓存的图像在500ms内弹回到位)。