【问题标题】:Javascript appendChild onload eventJavascript appendChild onload 事件
【发布时间】:2015-02-23 08:28:33
【问题描述】:

我将动态创建的图像元素附加到文档中。

var img = new Image();
img.src = 'test.jpg',
img.onload = function() {

    var addedImg = container.appendChild(img);
    console.log(img.width); //old width.
}

这里的问题是,如果我在container.appendChild(img) 之后立即获取图像尺寸,它会返回源文件尺寸,因为 appendChild 尚未完成(未重新绘制?)并且尺寸未重新计算。

var addedImg = container.appendChild(img);
console.log(img.width) //returns original width of the image

所以,我想知道是否可以捕获 appendChild 的加载事件?

我知道可以使用setTimeout/setInterval,但我想应该有更优雅的解决方案。

var addedImg = container.appendChild(img);
setTimeout(function() {
    console.log(img.width); //return correct resolution after image dimensions were recalculated
}, 1000);

setTimeout/setInterval 的问题在于我不知道元素何时最终被附加和重新绘制。我必须循环运行它。

我试图收听DOMNodeInsertedIntoDocumentDOMNodeInserted 事件,但它不起作用。

img.addEventListener("DOMNodeInserted", onImageInserted, false);
img.addEventListener("DOMNodeInsertedIntoDocument", onImageInserted, false);

function onImageInserted(event) {
    console.log(img.width); //still wrong width
}

但是,它似乎在 appendChild 被触发后立即运行。

这是小提琴,所以你可以看到我在说什么: http://jsfiddle.net/0zyybmf2/

注意:请不要检查父容器的宽度。我需要获取图像的宽度。 对此的任何帮助将不胜感激。

【问题讨论】:

  • 图片有load事件。
  • 例如:img.onload=function(){alert(this.naturalWidth)}
  • 我说的不是这个。此代码已在 img.load 中。这是关于捕捉重绘事件。
  • appendChild has not finished yet,什么?
  • 对不起,我不够清楚。我用小提琴更新了帖子,所以你可以看到它的实际效果。

标签: javascript addeventlistener appendchild


【解决方案1】:

不幸的是,您似乎必须将控件交还给浏览器(像您一样使用setTimeout())才能观察到最终尺寸;幸运的是,超时时间可能很短。

container.appendChild(img);
setTimeout(function() {
    console.log(img.width);
}, 0);

换句话说,只要你的函数返回并且在setTimeout 触发之前,重绘(和布局更新)就会完成。

顺便说一句,建议您仅在附加负载处理程序之后设置.src 属性;在我意识到缓存图像可能会在更改 .src 后立即触发加载处理程序之前,我不得不调试我的代码几次。

Demo

【讨论】:

  • 谢谢。但我知道setTimeout。我在原始问题中提到了这一点。 setTimeout 的问题在于我不知道何时重绘它。唯一可能的解决方案是检查 setTimeout 内是否更改了宽度(我认为setInterval 会更好)。我想知道是否有其他解决方案。
  • @Sray 好吧,你把超时值设置为 1 秒,这是不必要的;另外,为什么您需要确切知道重绘完成的时间?一旦你的函数完成,它就完成了,这就是重点。
  • 哦,我现在明白了。感谢您的完美解释。
  • 不需要setTimeout。参考我的回答。
  • @NK 是的,但是在您的回答中,您会在显示警报之前看到图像加载,这可能不是 OP 想要的。
【解决方案2】:

var img = new Image();
var container = document.getElementsByTagName("div")[0];
container.appendChild(img);

img.onload = function() {
  alert('Width = ' + img.width);
}

img.src = "http://globe-views.com/dcim/dreams/image/image-03.jpg";
div {
    width: 200px;
}

img {
    display: block;
    width: 100%;
    height: 100%;
}
<div></div>

【讨论】: