3

我对 jQuery 有疑问。

我想得到一个真实的宽度/高度img
现在我用这个函数来获取它:

var imageSize = function(image) {
    var realImageSize = { };

    $("<img/>") // Make in memory copy of image to avoid css issues
    .attr("src", $(image).attr("src"))
    .load(function() {
        realImageSize.width = this.width;   // Note: $(this).width() will not
        realImageSize.height = this.height; // work for in memory images.

        alert(realImageSize['height']); // Valid height
    });

    alert(realImageSize['height']); // Undefined

    return realImageSize;
}

所以我将图像复制到内存中,然后在.load方法中获取并设置图像的实际大小。

现在,问题是由于var realImageSize某种原因该变量在此范围内不可用。谁能告诉我为什么?

4

4 回答 4

6

这不是范围问题,很好,但同步性问题:您正在执行加载回调之前读取值。

您作为参数提供的回调load不会立即执行,而是仅在图像加载后执行。

通常的解决方案是不返回值而是提供回调:

var fetchImageSize = function(image, callback) {
    $("<img/>") // Make in memory copy of image to avoid css issues
    .load(function() {
        var realImageSize = { };
        realImageSize.width = this.width;   // Note: $(this).width() will not
        realImageSize.height = this.height; // work for in memory images.
        callback(realImageSize);
    }).attr("src", image.src);
};

fetchImageSize(myImage, function(realImageSize){
    alert(realImageSize['height']); // NOT Undefined
});

请注意,您应该始终在设置回调后设置 src。onload某些浏览器,如果您在缓存中有图像,如果您在设置源后设置它,则可能不会调用 onload 回调。

于 2013-01-31T10:02:08.003 回答
2

这是来自其他语言的 Javascript 程序员的常见问题。Javascript 使用称为异步调用的执行模型。简而言之,当您为.load()事件注册一个函数时,该函数的执行将推迟到图像已加载时,而函数体的其余部分(即 second alert())立即执行:

var imageSize = function(image) {
    //runs now
    var realImageSize = { };

    //runs now
    $("<img/>") // Make in memory copy of image to avoid css issues
    .attr("src", $(image).attr("src"))
    .load(function() {
        //this code can run say 5 sec later
        realImageSize.width = this.width;   // Note: $(this).width() will not
        realImageSize.height = this.height; // work for in memory images.

        alert(realImageSize['height']); // Valid height
    });

    //runs now. The realImageSize variable is yet to be created in 5 sec
    alert(realImageSize['height']); // Undefined

    //runs now
    return realImageSize;
}

解决此类问题的常见模式是将回调传递给需要很长时间的函数。

//** Get an image URL and a callback function that will be called when the image is loaded and the size is detected
function imageSize ( src, callback ) {
    $("<img src="' + src + '"/>").load( function () {
        //here we call the callback which will be called when the image is loaded
        callback({
            width: this.width,
            height: this.height
        });
    });
}

imageSize( 'my/image/path.png', function ( imageSize ) {
    //this callback function will be called when the image is loaded
    alert( 'width: ' + imageSize.width + ', height: ' + imageSize.height );
});
于 2013-01-31T10:12:29.180 回答
2

在加载函数完成之前调用您的第二个警报。使用回调...

尝试这个

var imageSize = function(image,callback) {
  var realImageSize = { };

  $("<img/>") // Make in memory copy of image to avoid css issues
  .attr("src", $(image).attr("src"))
  .load(function() {
    realImageSize.width = this.width;   // Note: $(this).width() will not
    realImageSize.height = this.height; // work for in memory images.

    alert(realImageSize['height']); // Valid height
    callback(realImageSize);
  });


}

imageSize(img, function(realImageSize) {
   alert(realImageSize.height);
});
于 2013-01-31T10:02:43.820 回答
2

使用回调。其他答案正在解释异步的东西,我不会重复:-)

var imageSize = function(image, callback) {
.
.
.
    .load(function() {
        realImageSize.width = this.width;   // Note: $(this).width() will not
        realImageSize.height = this.height; // work for in memory images.

        callback(realImageSize);
    });

然后,您可以像这样调用该函数:

imageSize(img, function(size) {
    alert(size.height);
});
于 2013-01-31T10:07:37.537 回答