1

我正在尝试将容器的纵横比与一系列图像的纵横比进行比较,并向图像添加类肖像或风景。此外,我正在尝试根据定义的容差检测非常高/宽的图像(如大全景图)。我有基本功能在这里工作(前两个图像在左上角有一个“缩放”按钮)。

现在,我正在尝试拆分函数,因此当我调整页面大小时,脚本不会再次计算所有图像的比率(var i_ratio),它只是将这些与新的容器比率(var c_ratio)进行比较。我的开发示例在这里

我想我的问题是我不知道如何:

  • 确保第二个功能在第一个功能完成后运行
  • 将 i_ratio 中的值从第一个函数传递到下一个函数

在开发示例中,有一个控制台日志显示 i_ratio 在第二个函数中未定义,但是当您调整窗口大小时,它似乎获得了一个值 - 不确定发生了什么。

// Get window aspect ratio
var container = $('.main');
var c_ratio = container.width() / container.height();
var i_ratio;

function imageRatios() {
  // Get original dimensions of image (IE8+)
  if (this.naturalWidth) {
    i_width = this.naturalWidth;
    i_height = this.naturalHeight;
  } else {
  // Get original dimensions of image with JQuery
    i_width = this.width;
    i_height = this.height;
  }
  i_ratio = i_width / i_height;
  // Don't allow images to get bigger than their original size
  $(this).css('max-width', i_width).css('max-height', i_height);
}

function setClass() {
  console.log('number of images: '+images.length+', i_ratio from imageRatios function: '+i_ratio);
  // Add ratio classes    
  if (c_ratio > i_ratio) {
    $(this).parent('li').removeClass('landscape').addClass('portrait');
  } else {
    $(this).parent('li').removeClass('portrait').addClass('landscape');
  }
  // Identify long/tall panoramas and add zoom button
  tolerance = c_ratio / i_ratio;
  if (tolerance < 0.3 || tolerance > 5) {
    $(this).after('<div class="zoom">&#xf065;</div>');
  } else {
    $(this).remove('.zoom');
  }
  // Show/hide zoomed image
  var img = $(this);
  $(this).next('.zoom').click(function() {
    if (img.siblings('.big_image').size() > 0) {
      $('.big_image').remove();
    } else {
      $(this).after('<div class="big_image"><img src="'+$img.attr('src')+'"></div>');        
    }
  });
}

// Get images
var images = $('.main img');
images.each(function(i) {
  if (this.complete) {
    imageRatios.call(this);
    setClass();
  } else {
    this.onload = imageRatios;
    setClass();
  }
});

// Update ratio class on resize
$(window).on("throttledresize", function() {
  var c_ratio = container.width() / container.height();
  images.each(function() {
    setClass();
  });
});
4

2 回答 2

1

几个问题 - 这将未经测试,因此您可能需要稍作调整以使其正确

  • 初始化图像时,您在设置卸载处理程序后立即调用 setClass。处理程序是异步的,因此立即调用 setClass 将导致您在控制台中看到的未定义值。
  • 图像比率都存储在同一个变量中。您将需要调整它以存储每个图像
  • 调用 setClass 时,调用 setClass 时没有设置上下文,因此this将是全局对象

获取图像逻辑可以调整为这样的:

// Get images
var images = $('.main img');
images.each(function(i) {
  if (this.complete) {
    imageRatios.call(this, i);
    setClass.call(this, i);   // <== call with image as the context and pass its index
  } else {
    // Wrap the calls to imageRatios & setClass in the callback so
    // they can be called sequentially
    this.onload = function() {
      imageRatios.call(this, i);
      setClass.call(this, i); // <== call with image as the context and pass its index
    };
  }
});

节流调整大小可以修改为:

// Update ratio class on resize
$(window).on("throttledresize", function() {
  c_ratio = container.width() / container.height(); // <== remove var - needs to be available to other functions in this closure (already declared at top)
  // TODO: Just need to update class, not recalculate image ratios on resize
  images.each(function(i) {
    setClass.call(this,i);   // <== call with image as the context and pass its index
  });
});

图像比率:

  var i_ratio = [];         // <== use an array of values indexes will match image indexes

  function imageRatios(i) { // <== change to accept an index
    var i_width, i_height;  // <== declare as local variables

    // Get original dimensions of image (IE8+)
    if (this.naturalWidth) {
      i_width = this.naturalWidth;
      i_height = this.naturalHeight;
    } else {
    // Get original dimensions of image with JQuery
      i_width = this.width;
      i_height = this.height;
    }
    i_ratio[i] = i_width / i_height;  // <== set the ratio using the passed in index
    // Don't allow images to get bigger than their original size
    $(this).css('max-width', i_width).css('max-height', i_height);
  }

设置类为:

  function setClass(i) {  // <== Change to accept an index
    var tolerance; // <== Declare as local variable
    console.log('number of images: '+images.length+', i_ratio from imageRatios function: '+i_ratio);
    // Add ratio classes    
    if (c_ratio > i_ratio[i]) { // <== Use the index to get the right ratio
      $(this).parent('li').removeClass('landscape').addClass('portrait');
    } else {
      $(this).parent('li').removeClass('portrait').addClass('landscape');
    }
    // Identify long/tall panoramas and add zoom button
    tolerance = c_ratio / i_ratio[i]; // <== Use the index to get the right ration
    if (tolerance < 0.3 || tolerance > 5) {
      $(this).after('<div class="zoom">&#xf065;</div>');
    } else {
      $(this).remove('.zoom');
    }
    // Show/hide zoomed image
    var img = $(this);
    $(this).next('.zoom').click(function() {
      if (img.siblings('.big_image').size() > 0) {
        $('.big_image').remove();
      } else {
        $(this).after('<div class="big_image"><img src="'+$img.attr('src')+'"></div>');        
      }
    });
  }
于 2013-09-07T03:47:30.257 回答
0

您未定义值的问题来自此代码

images.each(function (i) {
    if (this.complete) {
        imageRatios.call(this);
        setClass();
    } else {
        this.onload = imageRatios;
        setClass();
    }
});

这将每个图像的 onload 回调设置为imageRatios然后调用setClass()它但是不会等到onload事件被触发才能继续setClass尝试这样的事情

images.each(function (i) {
    if (this.complete) {
        imageRatios.call(this);
        setClass();
    } else {
        this.onload = function () {
            imageRatios();
            setClass();
        };
    }
});

当为图像触发事件imageRatios()setClass(),它将按顺序调用onload

于 2013-09-07T03:36:53.980 回答