Javascript窗口/图像加载计时 - 这应该不起作用,但它确实有效



这是一个简单的程序,用于加载两个图像,将第二个图像放在第一个图像的顶部,然后使用 setInterval 和不透明度更改将顶部图像淡入或淡出。 它运行良好,尽管查看代码,但如果在 topPic 之前加载 botPic(竞争条件),它应该会失败。 但它没有,我也想不通为什么它没有。

  window.onload = function() {
    var topPic = document.getElementById("topPic");
    var botPic = document.getElementById("botPic");
  }
  function findPosition(obj) {
    var curleft = 0;
    var curtop = 0;
    if (obj.offsetParent) {
      do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while ((obj = obj.offsetParent) !== null);
    }
    return [curleft, curtop];
  }
  function doTopPicLoad() {
    topPicLoaded = 1;
    if (botPicLoaded == 1) {
      startFader();
    }
  }
  function doBotPicLoad() {
    var leftTop = findPosition(botPic);
    topPic.style.left = leftTop[0];
    topPic.style.top  = leftTop[1];
    botPicLoaded = 1;
    if (topPicLoaded == 1) {
      startFader();
    }
  }
  function startFader() {
    // do stuff
  }
  <img id="botPic" onload='doBotPicLoad()' src="DMH_0991-M-72-720x576.jpg">
  <img id="topPic" onload='doTopPicLoad()' src="DMH_0991-72-720x576.jpg">

通过控制台或插入 DOM 进行日志记录.log始终将"window.load"显示为最后执行的项目。 doTopPicLoad 和 doBotPicLoad 以不同的顺序出现,但它们总是将 topPic 和 botPic 显示为有效对象。

topPic.onload [object HTMLImageElement] [object HTMLImageElement]
botPic.onload [object HTMLImageElement] [object HTMLImageElement]
startFader
window.onload

但是,如果我像这样开始,它通常(总是?)失败。

var topPic;
var botPic;
window.onload = function() {
  topPic = document.getElementById("topPic");
  botPic = document.getElementById("botPic");
}

我唯一的想法:

Javascript 解释器"知道"它必须延迟引用在 window.onload 函数中声明的任何变量的任何语句的执行 - 直到该函数完成。 (这似乎很牵强,但它可以解释它)。

我不想在我的代码中留下竞争条件,但似乎没有任何实际的"竞争"发生。 谁能解释为什么这段代码总是有效?

实际示例:http://www.davehennessey.com/photography/small-buildings/DMH_0991X2.html

谢谢 - 戴夫

您的窗口"加载"处理程序正在设置两个局部变量。您的脚本直接引用 DOM 元素<img>"topPic"和"botPic"。如果这两行不是以var开头,事情就不会真正改变,因为"topPic"和"botPic"已经指的是那些调用.getElementById()将返回的值。

也就是说,当你的代码(窗口"load"处理程序之外)引用变量"topPic"和"botPic"时,它访问的是通过这些名称绑定到窗口对象的 DOM 元素。浏览器这样做是因为元素具有这些"id"值。

由于在<img>元素"load"事件触发之前不会调用函数,因此可以正常工作。(在加载图像之前,设置<img>元素的"样式"将正常工作。您的窗口"加载"处理程序是多余的,对系统根本没有影响。

正如 Pointy 指出的那样,您的 topPic 和 botPic 变量仅是匿名 onload 函数的局部变量,不会影响页面的其余部分。

您是否考虑过定义 Pic 类?

function Pic(elem) {
  this.elem = elem;
  this.loaded = false
}
// define global objects topPic and botPic that have elem and loaded attributes
window.onload = function() {
    topPic = new Pic(document.getElementById("topPic"));
    botPic = new Pic(document.getElementById("botPic"));
  }
  function findPosition(obj) {
    var curleft = 0;
    var curtop = 0;
    if (obj.offsetParent) {
      do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while ((obj = obj.offsetParent) !== null);
    }
    return [curleft, curtop];
  }
  function doTopPicLoad() {
    topPic.loaded = true;
    if ( botPic.loaded ) {
      startFader();
    }
  }
  function doBotPicLoad() {
    var leftTop = findPosition(botPic.elem);
    topPic.elem.style.left = leftTop[0];
    topPic.elem.style.top  = leftTop[1];
    botPic.loaded = true;
    if ( topPic.loaded ) {
      startFader();
    }
  }
  function startFader() {
    // do stuff
  }

相关内容

最新更新