如何使用 Javascript/jQuery 确定图像是不是已加载?
Posted
技术标签:
【中文标题】如何使用 Javascript/jQuery 确定图像是不是已加载?【英文标题】:How can I determine if an image has loaded, using Javascript/jQuery?如何使用 Javascript/jQuery 确定图像是否已加载? 【发布时间】:2010-09-20 18:32:19 【问题描述】:我正在编写一些 javascript 来调整大图像的大小以适应用户的浏览器窗口。 (不幸的是,我不控制源图像的大小。)
所以 html 中会有这样的内容:
<img id="photo"
src="a_really_big_file.jpg"
title="this is some title text" />
我有没有办法确定img
标签中的src
图像是否已下载?
我需要这个,因为如果在浏览器加载图像之前执行$(document).ready()
,我会遇到问题。 $("#photo").width()
和 $("#photo").height()
将返回占位符(替代文本)的大小。就我而言,这类似于 134 x 20。
现在我只是检查照片的高度是否小于 150,并假设如果是,它只是替代文本。但这是一个相当大的技巧,如果照片的高度小于 150 像素(在我的特定情况下不太可能),或者 alt 文本的高度超过 150 像素(可能发生在小的浏览器窗口上),它就会中断.
编辑:对于任何想查看代码的人:
$(function()
var REAL_WIDTH = $("#photo").width();
var REAL_HEIGHT = $("#photo").height();
$(window).resize(adjust_photo_size);
adjust_photo_size();
function adjust_photo_size()
if(REAL_HEIGHT < 150)
REAL_WIDTH = $("#photo").width();
REAL_HEIGHT = $("#photo").height();
if(REAL_HEIGHT < 150)
//image not loaded.. try again in a quarter-second
setTimeout(adjust_photo_size, 250);
return;
var new_width = . . . ;
var new_height = . . . ;
$("#photo").width(Math.round(new_width));
$("#photo").height(Math.round(new_height));
);
更新:感谢您的建议。如果我为$("#photo").load
事件设置回调,则存在不会触发事件的风险,因此我直接在图像标签上定义了 onLoad 事件。作为记录,这是我最终使用的代码:
<img id="photo"
onload="photoLoaded();"
src="a_really_big_file.jpg"
title="this is some title text" />
然后在Javascript中:
//This must be outside $() because it may get called first
var isPhotoLoaded = false;
function photoLoaded()
isPhotoLoaded = true;
$(function()
//Hides scrollbars, so we can resize properly. Set with JS instead of
// CSS so that page doesn't break with JS disabled.
$("body").css("overflow", "hidden");
var REAL_WIDTH = -1;
var REAL_HEIGHT = -1;
$(window).resize(adjust_photo_size);
adjust_photo_size();
function adjust_photo_size()
if(!isPhotoLoaded)
//image not loaded.. try again in a quarter-second
setTimeout(adjust_photo_size, 250);
return;
else if(REAL_WIDTH < 0)
//first time in this function since photo loaded
REAL_WIDTH = $("#photo").width();
REAL_HEIGHT = $("#photo").height();
var new_width = . . . ;
var new_height = . . . ;
$("#photo").width(Math.round(new_width));
$("#photo").height(Math.round(new_height));
);
【问题讨论】:
这太老了,您已经接受了答案,所以我将在这里发表评论。为什么不能使用 jQuery 插件“onImagesLoad”?而且,无论是否使用 jQuery,使用 Javascript 在图像样式中设置max-width
和 max-height
有什么问题?然后,您可以通过将最大宽度/高度设置为视口宽度/高度的大小来避免您需要编写的所有代码。
@jon.wd7:我不熟悉那个插件,它可能早在 08 年就没有了。至于最大宽度和最大高度,有两件事:1)IE 不支持它们(我不确定 IE 8); 2)如果视口改变大小(窗口大小调整等),那么我仍然需要javascript来改变最大宽度/最大高度(尽管如果我使用“100%”而不是像素测量,我可能不会)
根据 quirksmode.org 的说法,IE7 和 IE8 肯定支持它。所以我不确定你的问题。对于这样的小事,我个人不支持 IE6,所以他们看到的和没有启用 JS 的用户看到的一样。当然,您需要在调整大小时重置 max-width
和 max-height
。但这是一项相当容易的任务,实际上是使用.resize()
的单行代码。
complete 属性提供了了解图像是否已加载的必要方式。
@Adrien,Mozilla 现在 shows 已完成,所有主流浏览器都支持,除了 Andoid(未知)。
【参考方案1】:
要么添加一个事件侦听器,要么让图像通过 onload 宣布自己。然后从那里找出尺寸。
<img id="photo"
onload='loaded(this.id)'
src="a_really_big_file.jpg"
title="this is some title text" />
【讨论】:
根据规范,onload只是body和frameset元素的事件;也就是说,我认为这在 IE 中有效,但我不知道它在任何其他浏览器中也有效,或者你可以假设它是什么......我几周前只是在研究这个......跨度> 我已经在 IE6、IE7、FF3、Opera9、Safair (Windows Beta) 和 Chrome (Windows Beta) 中进行了测试。 不鼓励乱发行为和内容。事件应该使用 Javascript,而不是 HTML。 他的评论是相关的,因为我们没有被困在 2008 年。人们仍在阅读这篇文章,即使它在 08 年被认为不是坏做法,你也不希望人们现在认为它是好的做法。 document.querySelector("img").addEventListener("load", function() alert('onload!'); );【参考方案2】:使用jquery data store,您可以定义“加载”状态。
<img id="myimage" onload="$(this).data('loaded', 'loaded');" src="lolcats.jpg" />
然后你可以在其他地方做:
if ($('#myimage').data('loaded'))
// loaded, so do stuff
【讨论】:
使用jQuery(this)
而不是$(this)
以更好地与其他库兼容(jquery 不拥有 $),尤其是当您在 html 中有 JavaScript 时。【参考方案3】:
正确答案是使用event.special.load
如果从浏览器缓存中加载图片,可能不会触发加载事件。为了解决这种可能性,我们可以使用一个特殊的加载事件,如果图像准备好,它会立即触发。 event.special.load 目前可作为插件使用。
根据.load() 上的文档
【讨论】:
我打算用这样的建议添加一个答案,很高兴我在编码之前看到了这个答案。基本上,您的处理程序需要在设置处理程序之前首先检查图像是否已加载。如果它已经加载,立即触发回调。这就是$.ready
所做的。我本来建议只检查宽度,但这有问题,我真的很喜欢这个解决方案。【参考方案4】:
您想按照艾伦所说的去做,但是请注意,有时图像会在 dom 准备好之前加载,这意味着您的加载处理程序不会触发。最好的方法是按照艾伦所说的做,但在附加负载处理程序后使用 javascript 设置图像的 src。这样你就可以保证它会触发。
在可访问性方面,您的网站是否仍然适用于没有 javascript 的人?您可能希望为 img 标签提供正确的 src,附加您的 dom 就绪处理程序以运行您的 js:清除图像 src(使用 css 给它一个固定的高度以防止页面闪烁),然后设置您的 img 加载处理程序,然后将 src 重置为正确的文件。这样你就覆盖了所有的基础:)
【讨论】:
该网站仍然适用于没有 Javascript 的人,他们只需滚动即可查看所有图像。【参考方案5】:根据最近对您原始问题的回答之一
$(function()
$(window).resize(adjust_photo_size);
adjust_photo_size();
function adjust_photo_size()
if (!$("#photo").get(0).complete)
$("#photo").load(function()
adjust_photo_size();
);
else
...
);
警告 这个答案可能会导致 ie8 及更低版本出现严重循环,因为浏览器并不总是正确设置 img.complete。如果您必须支持 ie8,请使用一个标志来记住图像已加载。
【讨论】:
持有它。这个答案可能会在 ie8 及更低版本中导致严重的循环,因为浏览器并不总是正确设置 img.complete。如果必须支持 ie8,请使用标志来记住已加载图像。【参考方案6】:尝试类似:
$("#photo").load(function()
alert("Hello from Image");
);
【讨论】:
谢谢。但是,有可能在此之前图像已经加载,在这种情况下不会触发 load 事件。 在图片标签之后设置这个事件的脚本标签怎么样?使用 ready 的原因是确保整个文档都已加载,在这种情况下这是不必要的,对吧?【参考方案7】:有一个名为“imagesLoaded”的 jQuery 插件,它提供了一种跨浏览器兼容的方法来检查元素的图像是否已加载。
网站:https://github.com/desandro/imagesloaded/
用于内部有许多图像的容器:
$('container').imagesLoaded(function()
console.log("I loaded!");
)
插件很棒:
-
用于检查包含许多图像的容器
用于检查 img 是否已加载
【讨论】:
似乎有点重 5KB 缩小只是为了检查 img 加载。应该是一种更简单的打火机方法......【参考方案8】:我发现这对我有用
document.querySelector("img").addEventListener("load", function() alert('onload!'); );
这完全归功于 Frank Schwieterman,他对接受的答案发表了评论。不得不放这里,太贵重了……
【讨论】:
【参考方案9】:这个有cmet吗?
...
doShow = function()
if($('#img_id').attr('complete'))
alert('Image is loaded!');
else
window.setTimeout('doShow()',100);
;
$('#img_id').attr('src','image.jpg');
doShow();
...
似乎无处不在...
【讨论】:
使用setTimeout
是不好的做法【参考方案10】:
我刚刚创建了一个 jQuery 函数来使用 jQuerys Deferred Object 加载图像,这使得对加载/错误事件做出反应非常容易:
$.fn.extend(
loadImg: function(url, timeout)
// init deferred object
var defer = $.Deferred(),
$img = this,
img = $img.get(0),
timer = null;
// define load and error events BEFORE setting the src
// otherwise IE might fire the event before listening to it
$img.load(function(e)
var that = this;
// defer this check in order to let IE catch the right image size
window.setTimeout(function()
// make sure the width and height are > 0
((that.width > 0 && that.height > 0) ?
defer.resolveWith :
defer.rejectWith)($img);
, 1);
).error(function(e)
defer.rejectWith($img);
);
// start loading the image
img.src = url;
// check if it's already in the cache
if (img.complete)
defer.resolveWith($img);
else if (0 !== timeout)
// add a timeout, by default 15 seconds
timer = window.setTimeout(function()
defer.rejectWith($img);
, timeout || 15000);
// return the promise of the deferred object
return defer.promise().always(function()
// stop the timeout timer
window.clearTimeout(timer);
timer = null;
// unbind the load and error event
this.off("load error");
);
);
用法:
var image = $('<img />').loadImg('http://www.google.com/intl/en_com/images/srpr/logo3w.png')
.done(function()
alert('image loaded');
$('body').append(this);
).fail(function()
alert('image failed');
);
查看它的工作原理:http://jsfiddle.net/roberkules/AdWZj/
【讨论】:
听起来很棒。您能否给出一个确切的例子,说明您的代码何时优于 img.onload 和 img.onerror?您的代码是否仅用于处理我刚刚获悉的 jQuery 错误处理的看似缺点:如果没有文件扩展名,该错误不会在 IE 中触发? 有趣的想法。所以知道图像何时完成很容易。但是,如果无法加载图像怎么办。我正在寻找一种方法来知道加载图像是否失败。你给了我超时加载它的想法。为此 +1 @oak 超时应该只是一个后备。大多数浏览器应该触发由.error(function(e) defer.rejectWith($img); )
处理的error
事件。如果您查看 jsFiddle,您将看到 http://www.google.com/abc.png not found
文本立即显示在结果窗格中(不等待超时,因为错误事件已启动)
请注意,jquery 引发 .error 的两件事应该是 1. 句柄,但要在引发错误之前设置。 2. .error 只处理 http 协议而不是 file:// 所以你不会在那里出错..
在我的代码示例中,成功/错误处理程序是在完全为此原因分配 src 属性之前设置的。关于file://
限制 - 我从来不需要使用文件协议链接图像,我认为没有太多需要。【参考方案11】:
此函数根据可测量的尺寸检查图像是否已加载。如果您的脚本在某些图像已经加载后执行,则此技术很有用。
imageLoaded = function(node)
var w = 'undefined' != typeof node.clientWidth ? node.clientWidth : node.offsetWidth;
var h = 'undefined' != typeof node.clientHeight ? node.clientHeight : node.offsetHeight;
return w+h > 0 ? true : false;
;
【讨论】:
我发现此解决方案可能要求图像上没有边距或填充,并提供空字符串的替代文本。但在大多数情况下,它按预期工作。仅当卸载图像的大小大于零时才会失败。【参考方案12】:我们开发了一个页面,它在其中加载了许多图像,然后仅在加载图像后才执行其他功能。这是一个繁忙的网站,产生了大量的流量。似乎以下简单脚本几乎适用于所有浏览器:
$(elem).onload = function()
doSomething();
但这是 IE9 的潜在问题!
我们报告问题的唯一浏览器是 IE9。我们不感到惊讶吗?似乎解决该问题的最佳方法是在定义 onload 函数之前不为图像分配 src,如下所示:
$(elem).onload = function()
doSomething();
$(elem).attr('src','theimage.png');
似乎 IE 9 有时无论出于何种原因都不会抛出 onload
事件。此页面上的其他解决方案(例如来自 Evan Carroll 的解决方案)仍然无效。从逻辑上讲,它检查了加载状态是否已经成功并触发了函数,如果没有,则设置 onload 处理程序,但即使你这样做了,我们在测试中也证明了图像可以在这两行 js 之间加载显示未加载到第一行,然后在设置 onload 处理程序之前加载。
我们发现获得所需内容的最佳方法是在设置 onload
事件触发器之前不要定义图像的 src。
我们最近才停止支持 IE8,所以我不能说 IE9 之前的版本,否则,在网站上使用的所有其他浏览器中——IE10 和 11 以及 Firefox、Chrome、Opera, Safari 和人们使用的任何移动浏览器——在分配 onload
处理程序之前设置 src
甚至都不是问题。
【讨论】:
【参考方案13】:我可以推荐一个纯 CSS 解决方案吗?
只要有一个要在其中显示图像的 Div。将图像设置为背景。然后根据您的需要拥有属性background-size: cover
或background-size: contain
。
cover
将裁剪图像,直到较小的边覆盖框。
contain
会将整个图像保留在 div 中,并在两侧留出空格。
检查下面的sn-p。
div
height: 300px;
width: 300px;
border: 3px dashed grey;
background-position: center;
background-repeat: no-repeat;
.cover-image
background-size: cover;
.contain-image
background-size: contain;
<div class="cover-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
<br/>
<div class="contain-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
【讨论】:
【参考方案14】:我发现这个简单的解决方案最适合我:
function setEqualHeight(a, b)
if (!$(a).height())
return window.setTimeout(function() setEqualHeight(a, b); , 1000);
$(b).height($(a).height());
$(document).ready(function()
setEqualHeight('#image', '#description');
$(window).resize(function()setEqualHeight('#image', '#description'));
);
</script>
【讨论】:
【参考方案15】:image.complete 可能是另一种选择 https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/complete
【讨论】:
虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。 Answers that are little more than a link may be deleted以上是关于如何使用 Javascript/jQuery 确定图像是不是已加载?的主要内容,如果未能解决你的问题,请参考以下文章
Javascript/jQuery/JSON/localStorage 游戏,无法按数字排序排名表
如何使用 jquery/javascript 将文本插入 json [重复]
如何使用 JavaScript/JQuery 创建一个简单的地图 [重复]