0

我有一个特殊的问题。我正在加载一个 JSON 文件,其中包含许多图像的 src、宽度和高度。

我正在尝试将它们加载到平滑脚本 jquery 插件中并让图像自动滚动。

“查看区域” div 可以并排放置三个图像。

当我第一次加载页面时,只显示第一张图片。如果我重新加载它,会显示前三张图片,然后加载其他(总共有 11 张),但插件不会滚动,所以你看不到它们。

当我在 $(window).one 函数中插入 alert("whatever") 行时,一切正常。

我怀疑这与加载图像和触发 .load 事件的时间有关。

下面是解析 JSON 文件并创建附加到可滚动 div 的 HTML 字符串的代码:

var aSectionImages = new Array;
var aImagesCount = new Array();
var aImagesLoaded = new Array();
var htmlString;
var jsonStyleImages = "images.json"
 var jsonNavImages = "imagesNav.json";
var scrollableArea = $("#scrollableArea");
$.getJSON(jsonNavImages, getNavIcons);
$.getJSON(jsonStyleImages, makeScroller);

function imageLoaded(imgSrc){
 var locId = (imageInSection(imgSrc)).replace(/\s|'/g, "_");
 if (aImagesLoaded[locId]===undefined){
  aImagesLoaded[locId] = 0;
 };     
 aImagesLoaded[locId] = aImagesLoaded[locId]+1;
 if (aImagesLoaded[locId]==aImagesCount[locId]){
  //alert("section" + locId);
  //$("#loaded").html(locId);
  //aSectionLoaded = {locId:"loaded"};

  //in theory, wait until all images in a section are loaded before
  //appending the HTML to the div:
  scrollableArea.append(htmlString);
 }
}

function imageInSection(src){
 var resultId=false;
 var locSrc = src.split("/");
 var locFileName = (locSrc[locSrc.length-1]);
 for (i = 0; i < aSectionImages.length; i++){
   for(j=0; j < aSectionImages[i].images.length; j++){
    tempSrc = aSectionImages[i].images[j].src.split("/");
    tempFileName = tempSrc[tempSrc.length-1];
    if (tempFileName == locFileName) {
     resultId = aSectionImages[i].id;
    }
   }
 }
 return resultId;
}

function makeScroller(data){
 aSectionImages = data;
 for (i=0; i<aSectionImages.length;i++){
  locData = aSectionImages[i];
  locId = locData.id.replace(/\s|'/g, "_");
  aImagesCount[locId] = locData.images.length;
  htmlString = "<div id=\"" + locId + "\">";

   for (j=0; j<locData.images.length; j++){
    oImage = new Image();
    $(oImage)
     .load(function(){
      imageLoaded(this.src);
    })
     .attr("src", locData.images[j].src);

     if (oImage.complete && oImage.naturalWidth !== 0){
     $(this).trigger("load");
     //$("#trigger").html(locData.images[j].src);
     //return false;
     }
    locImage = locData.images[j];
    locImage.id ? locImage.id = " id=\""+locImage.id+"\" " : locImage.id = "";
    htmlString += "<img height=\"" + locImage.height + "\"" + " width=\"" + locImage.width + "\"" + locImage.id + " src=\"" + locImage.src + "\" />";
   }       
 }

}

这是处理加载时显示图像的插件的一部分:

// 加载时要做的事情 $(window).one("load",function(){ //alert("如果我在此处包含警报,为什么它会起作用?");

// If the content of the scrolling area is not loaded through ajax,
// we assume it's already there and can run the code to calculate
// the width of the scrolling area, resize it to that width
if(options.ajaxContentURL.length === 0) {
 $mom.scrollableAreaWidth = 0;
 $mom.tempStartingPosition = 0;

 $mom.find(options.scrollableArea).children().find("img").each(function() {

  // Check to see if the current element in the loop is the one where the scrolling should start
  if( (options.startAtElementId.length !== 0) && (($(this).attr("id")) == options.startAtElementId) ) {
  $mom.tempStartingPosition = $mom.scrollableAreaWidth;
  }

  // Add the width of the current element in the loop to the total width
  $mom.scrollableAreaWidth = $mom.scrollableAreaWidth + $(this).outerWidth(true);
 });

 // Set the width of the scrollableArea to the accumulated width
 $mom.find(options.scrollableArea).css("width", $mom.scrollableAreaWidth + "px");

 // Check to see if the whole thing should be hidden at start
 if(options.hiddenOnStart) {
  $mom.hide();
 }
}

// Set the starting position of the scrollable area. If no startAtElementId is set, the starting position
// will be the default value (zero)
$mom.find(options.scrollWrapper).scrollLeft($mom.tempStartingPosition);

// If the user has set the option autoScroll, the scollable area will
// start scrolling automatically
if(options.autoScroll !== "") {
 $mom.autoScrollInterval = setInterval(autoScroll, $mom.autoScrollDelay);
}

// If autoScroll is set to always, the hot spots should be disabled
if(options.autoScroll == "always")
{
 hideLeftHotSpot();
 hideRightHotSpot();
}

// If the user wants to have visible hot spots, here is where it's taken care of
switch(options.visibleHotSpots)
{
 case "always":
  makeHotSpotBackgroundsVisible();
  break;
 case "onstart":
  makeHotSpotBackgroundsVisible();
  $mom.hideHotSpotBackgroundsInterval = setInterval(hideHotSpotBackgrounds, (options.hotSpotsVisibleTime * 1000));
  break;
 default:
  break; 
}

});

完整代码位于 http://chereecheree.com/dagworthy/style.html

您会注意到,如果您重新加载页面,它会按预期工作,但如果您从上一层 (dagwothy/) 访问链接,则只会加载第一个图像,除非在加载时抛出警报语句。

感谢您花时间研究这个!——丹尼尔。

4

1 回答 1

3

我认为您的问题就在这里,或者至少是我看到的第一个问题:

oImage = new Image();
$(oImage).load(function(){
  imageLoaded(this.src);
}).attr("src", locData.images[j].src);

if (oImage.complete && oImage.naturalWidth !== 0){
  $(this).trigger("load");
}

在这种情况下this不是oImage(就像在 a 中一样.each()),它是document,所以你在load错误的元素上触发了,你需要拥有$(oImage).trigger("load")or$(oImage).load()代替。

您尝试处理的情况是load手动触发,因为并非所有浏览器在从缓存加载图像时都会触发它是正确的想法......您只需要在正确的元素上触发事件,否则这种情况永远不会成立,因为所有这些图像从来没有load增加计数的事件:

if (aImagesLoaded[locId]==aImagesCount[locId]){

alert()给了图像加载时间,所以在其他任何事情继续之前一切都准备好了......这本身就会抛出你窗外的任何竞争条件,所以当这种情况发生时,通常是 a) 加载了一些没有时间的依赖项之前,或者b)通过给第一个时间来加载某些事件顺序被抛出......这通常也是a部分。

于 2010-07-01T12:19:44.977 回答