如何创建 JavaScript 回调以了解图像何时加载?
Posted
技术标签:
【中文标题】如何创建 JavaScript 回调以了解图像何时加载?【英文标题】:How to create a JavaScript callback for knowing when an image is loaded? 【发布时间】:2010-09-21 18:10:58 【问题描述】:我想知道图像何时完成加载。有没有办法通过回调来做到这一点?
如果没有,有没有办法做到这一点?
【问题讨论】:
github.com/desandro/imagesloaded - 伙计们,看看这个包。 【参考方案1】:.complete
+ 回调
这是一种符合标准的方法,没有额外的依赖项,并且无需等待:
var img = document.querySelector('img')
function loaded()
alert('loaded')
if (img.complete)
loaded()
else
img.addEventListener('load', loaded)
img.addEventListener('error', function()
alert('error')
)
来源:http://www.html5rocks.com/en/tutorials/es6/promises/
【讨论】:
如果图像在img.complete
调用和addEventListener
调用之间完成,这会出错吗?
@ThomasAhle 我不是专家,但这似乎是可能的。让我们看看是否有人有解决方案。
我猜这只是并行代码的问题,而大多数 javascript 可能不是......
@ThomasAhle 不能,因为浏览器只会在事件队列旋转时触发 load 事件。也就是说,load
事件侦听器 必须 在 else
子句中,因为 img.complete
可以在 load
事件被触发之前变为真,因此如果不是,你可能会两次调用loaded
(注意这很可能发生变化,img.complete
仅在事件触发时才变为真)。【参考方案2】:
Image.onload() 通常会起作用。
要使用它,您需要确保在设置 src 属性之前绑定事件处理程序。
相关链接:
Mozilla on Image.onload()示例用法:
window.onload = function ()
var logo = document.getElementById('sologo');
logo.onload = function ()
alert ("The image has loaded!");
;
setTimeout(function()
logo.src = 'https://edmullen.net/test/rc.jpg';
, 5000);
;
<html>
<head>
<title>Image onload()</title>
</head>
<body>
<img src="#" id="sologo"/>
<script type="text/javascript">
</script>
</body>
</html>
【讨论】:
仅供参考:根据 W3C 规范,onload 不是 IMG 元素的有效事件。显然浏览器确实支持它,但如果你关心规范并且不能 100% 确定你想要定位的所有浏览器都支持它,你可能需要重新考虑它或至少牢记它。 为什么等待 5 秒来设置源似乎是个坏主意? @quemeful 这就是为什么它被称为“一个例子”。 @JasonBunting 你在看什么让你认为load
事件无效? html.spec.whatwg.org/multipage/webappapis.html#handler-onload 是onload
事件处理程序的定义。
@gsnedders - 你意识到,我假设,当我写那条评论时,我指的是现存的标准,而不是你指出的那个,它比 4.5 年新。如果你当时问过,我可能会指出它。这就是网络的本质,对吧?东西变旧或被移动或被修改等。【参考方案3】:
您可以使用 Javascript 图像类的 .complete 属性。
我有一个应用程序,我在一个数组中存储了许多 Image 对象,这些对象将被动态添加到屏幕上,并且当它们加载时,我将更新写入页面上的另一个 div。这是一个代码sn-p:
var gAllImages = [];
function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
gAllImages = [];
for (var i = thumbnailsBegin; i < thumbnailsEnd; i++)
var theImage = new Image();
theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
gAllImages.push(theImage);
setTimeout('checkForAllImagesLoaded()', 5);
window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;
// make a new div containing that image
makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
function checkForAllImagesLoaded()
for (var i = 0; i < gAllImages.length; i++)
if (!gAllImages[i].complete)
var percentage = i * 100.0 / (gAllImages.length);
percentage = percentage.toFixed(0).toString() + ' %';
userMessagesController.setMessage("loading... " + percentage);
setTimeout('checkForAllImagesLoaded()', 20);
return;
userMessagesController.setMessage(globals.defaultTitle);
【讨论】:
我以前在工作中使用过类似的代码。这适用于所有浏览器。 检查完成的问题是,从 IE9 开始,OnLoad 事件在所有图像加载之前触发,现在很难找到检查功能的触发器。【参考方案4】:jquery 的生命太短暂了。
function waitForImageToLoad(imageElement)
return new Promise(resolve=>imageElement.onload = resolve)
var myImage = document.getElementById('myImage');
var newImageSrc = "https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620"
myImage.src = newImageSrc;
waitForImageToLoad(myImage).then(()=>
// Image have loaded.
console.log('Loaded lol')
);
<img id="myImage" src="">
【讨论】:
这是一个很好的答案,但我认为您甚至不需要那么多代码。通过在 JS 中添加src
只是让它看起来很混乱。
时间是编程的一个巨大限制。根据我的经验,编写可读(有时很长)的代码会带来巨大的时间收益。
为什么要将 src 存储到一个新变量中,只是为了在下一行使用它?如果简洁是您的目标,那就是反模式。 myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620
成功了。【参考方案5】:
您可以在 jQuery 中使用 load() 事件,但如果图像是从浏览器缓存中加载的,它不会总是触发。这个插件https://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js 可以用来解决这个问题。
【讨论】:
【参考方案6】:这是 jQuery 等价物:
var $img = $('img');
if ($img.length > 0 && !$img.get(0).complete)
$img.on('load', triggerAction);
function triggerAction()
alert('img has been loaded');
【讨论】:
【参考方案7】:当这个问题被问到时,不适合 2008 年,但这些天这对我来说效果很好:
async function newImageSrc(src)
// Get a reference to the image in whatever way suits.
let image = document.getElementById('image-id');
// Update the source.
img.src = src;
// Wait for it to load.
await new Promise((resolve) => image.onload = resolve; );
// Done!
console.log('image loaded! do something...');
【讨论】:
【参考方案8】:如果目标是在浏览器渲染图像后设置 img 样式,您应该:
const img = new Image();
img.src = 'path/to/img.jpg';
img.decode().then(() =>
/* set styles */
/* add img to DOM */
);
因为浏览器首先是loads the compressed version of image
,然后是decodes it
,最后是paints
。由于paint
没有事件,您应该在浏览器具有decoded
img 标签后运行您的逻辑。
【讨论】:
【参考方案9】:这些函数将解决问题,您需要实现DrawThumbnails
函数并有一个全局变量来存储图像。我喜欢让它与具有ThumbnailImageArray
作为成员变量的类对象一起使用,但我很挣扎!
在addThumbnailImages(10);
中调用
var ThumbnailImageArray = [];
function addThumbnailImages(MaxNumberOfImages)
var imgs = [];
for (var i=1; i<MaxNumberOfImages; i++)
imgs.push(i+".jpeg");
preloadimages(imgs).done(function (images)
var c=0;
for(var i=0; i<images.length; i++)
if(images[i].width >0)
if(c != i)
images[c] = images[i];
c++;
images.length = c;
DrawThumbnails();
);
function preloadimages(arr)
var loadedimages=0
var postaction=function()
var arr=(typeof arr!="object")? [arr] : arr
function imageloadpost()
loadedimages++;
if (loadedimages==arr.length)
postaction(ThumbnailImageArray); //call postaction and pass in newimages array as parameter
;
for (var i=0; i<arr.length; i++)
ThumbnailImageArray[i]=new Image();
ThumbnailImageArray[i].src=arr[i];
ThumbnailImageArray[i].onload=function() imageloadpost();;
ThumbnailImageArray[i].onerror=function() imageloadpost();;
//return blank object with done() method
//remember user defined callback functions to be called when images load
return done:function(f) postaction=f || postaction ;
【讨论】:
这段代码大部分是不相关的,包括你的整个addThumbnailImages
函数。将其缩减为相关代码,我将删除 -1。【参考方案10】:
如果你使用 React.js,你可以这样做:
render()
// ...
<img
onLoad=() => this.onImgLoad( item )
onError=() => this.onImgLoad( item )
src=item.src key=item.key
ref=item.key />
// ...
在哪里:
- onLoad (...) 现在将调用如下内容: 源:“https://......png”,键:“1” 您可以将其用作“关键”来了解哪些图像已正确加载,哪些未正确加载。 - onError(...) 它是相同的,但对于错误。 - 对象 "item" 是这样的 key:"..", src:".." 您可以使用存储图像的 URL 和密钥,以便在图像列表中使用。【讨论】:
以上是关于如何创建 JavaScript 回调以了解图像何时加载?的主要内容,如果未能解决你的问题,请参考以下文章