使用Flickr中的jQuery获取图像的高度而不加载图像文件?

时间:2011-09-13 11:44:15

标签: jquery ajax image rss flickr

我目前正在开发一个jQuery解决方案,我想从Flickr RSS-feed加载图像。我对从Feed中获得的默认大小不满意 - 我希望我加载的图像等于或高于我正在显示它们的包装元素的高度。(宽度在这里不是问题。)

根据他们的API documentation,Flickr的图像尺寸系统如下所示:

s   small square 75x75
t   thumbnail, 100 on longest side
m   small, 240 on longest side
-   medium, 500 on longest side
z   medium 640, 640 on longest side
b   large, 1024 on longest side*
o   original image, either a jpg, gif or png, depending on source format

* Before May 25th 2010 large photos only exist for very large original images

这意味着没有保证的高度 - 我需要检查我要加载的每个图像的高度。例如:如果图像是全景图并且我加载了大尺寸,则高度可能仍然不足以填充我的包装元素。这是因为最长边是宽度,它将是1024.

为了使事情复杂化,包装器的高度可能会有所不同 - 在页面加载后不是动态的,而是从页面到页面。在某些页面上它是300像素,在其他页面上它是100像素,依此类推。

据我所知,获取图像文件高度的唯一方法是实际加载它。所以我写了一些加载图像的递归代码,看看它的高度,如果它还不够,它再次调用自己来加载下一个大小。在当前版本中,它以最小的尺寸开始,并一直向上,直到找到合适的图像或最大的图像。

以下是代码:

$.getJSON(ajaxContentURL, function(data) {
        var flickrImages = [];

        // An array of object with data pertaining Flickr's image sizes
        var flickrImageSizes = [{ size: "small square", pixels: 75, letter: "_s" }, 
                                { size: "thumbnail", pixels: 100, letter: "_t" }, 
                                { size: "small", pixels: 240, letter: "_m" }, 
                                { size: "medium", pixels: 500, letter: "" }, 
                                { size: "medium 640", pixels: 640, letter: "_z" }, 
                                { size: "large", pixels: 1024, letter: "_b"}];

        $.each(data.items, function(index, item) {
            flickrImages.push(loadFlickrImage(item, 0));
        });

        function loadFlickrImage(item, sizeIndex) {
            var path = item.media.m;
            var imgSrc = path.replace("_m", flickrImageSizes[sizeIndex].letter);
            var tempImg = $("<img />").attr("src", imgSrc);

            tempImg.load(function() {
               // Is it still smaller? Load next size
               if (this.height < el.data("scrollableAreaHeight")) {
                    // Load a bigger image, if possible
                    if ((sizeIndex + 1) < flickrImageSizes.length) {
                        loadFlickrImage(item, sizeIndex + 1);
                    } else {
                        return this;
                    }
               else {
                    return this;
               }
            });
        }
});

这是一个粗糙的边缘,但我希望你得到的图片。

这样可行,但为了获得合适的尺寸而必须加载如此多的图像版本似乎很浪费?

您有任何改进建议吗?我认为它应该首先进行合格的猜测,这可能是最好的尺寸并首先加载它。然后它会看它是否合适,或者它是否太小或太大,并在尺寸范围内加载下一个或上一个图像。这样,您可以减少要加载的图像数量,以获得正确的大小。

更好的是:有没有办法在不加载实际图像文件的情况下找出图像尺寸?请记住,我无法访问完整的Flickr API - 我只是访问JSON-feed like this one

我很感激任何反馈!

提前致谢!

4 个答案:

答案 0 :(得分:1)

也许我对问题的理解是错误的,但也许在html中设置高度,然后通过jquery调整大小到最大的最佳尺寸?加载所有图像的最大实际尺寸将是浪费,但它比不止一次加载图像更好。

对于html设置,只要记住尽可能小的图像以防止空白填充。当然,设置一个维度将允许另一个维度自我设置。如果裁剪是一个问题,一个hack是设置包装器的大小和溢出:隐藏。

对于jquery调整大小,假设图像不会立即加载,观看者可能会看到图像改变大小并不理想。除非你将它们保持隐藏状态直到装入,调整大小,然后显示

答案 1 :(得分:1)

我已经通过首先对哪个图像尺寸可能是最佳图像进行合格猜测来解决这个问题。此猜测基于加载图像将放入其中的元素的高度。然后我加载这个合理的图像大小,看它是否足够高。如果它高于或等于所需的高度,我会使用它。否则我会加载下一个更大的尺寸,检查它的高度等等。

即使这可能意味着我将加载更多的图像,而不是首先加载最大的图像,我认为它在加载的千字节总量方面更便宜。一些初步测试表明,从20个Flickr图像的标准馈送中,需要在第一次加载后重新加载1或2个图像。

如果您将此解决方案用于测试并最终得到不同的结果或思考,请告诉我,而不是我的方法是错误的。我正在寻找最便宜和最好的解决方案。

如果有兴趣的话,这是当前的代码:

$.getJSON(flickrJsonUrl, function(data) {
    // small square - size is 75x75
    // thumbnail -> large - size is the longest side
    var flickrImageSizes = [{ size: "small square", pixels: 75, letter: "_s" },
                            { size: "thumbnail", pixels: 100, letter: "_t" },
                            { size: "small", pixels: 240, letter: "_m" },
                            { size: "medium", pixels: 500, letter: "" },
                            { size: "medium 640", pixels: 640, letter: "_z" },
                            { size: "large", pixels: 1024, letter: "_b"}];
    var loadedFlickrImages = [];
    var startingIndex;
    var numberOfFlickrItems = data.items.length;
    var loadedFlickrImagesCounter = 0;

    // Determine a plausible starting value for the image height
    if (el.data("scrollableAreaHeight") <= 75) {
        startingIndex = 0;
    } else if (el.data("scrollableAreaHeight") <= 100) {
        startingIndex = 1;
    } else if (el.data("scrollableAreaHeight") <= 240) {
        startingIndex = 2;
    } else if (el.data("scrollableAreaHeight") <= 500) {
        startingIndex = 3;
    } else if (el.data("scrollableAreaHeight") <= 640) {
        startingIndex = 4;
    } else {
        startingIndex = 5;
    }

    // Put all items from the feed in an array.
    $.each(data.items, function(index, item) {
        loadFlickrImage(item, startingIndex);
    });

    function loadFlickrImage(item, sizeIndex) {
        var path = item.media.m;
        var imgSrc = path.replace("_m", flickrImageSizes[sizeIndex].letter);
        var tempImg = $("<img />").attr("src", imgSrc);

        tempImg.load(function() {
            // Is it still smaller? Load next size
            if (this.height < el.data("scrollableAreaHeight")) {
                // Load a bigger image, if possible
                if ((sizeIndex + 1) < flickrImageSizes.length) {
                    loadFlickrImage(item, sizeIndex + 1);
                } else {
                    addImageToLoadedImages(this);
                }
            } else {
                addImageToLoadedImages(this);
            }

            // Finishing stuff to do when all images have been loaded
            if (loadedFlickrImagesCounter == numberOfFlickrItems) {
                // DO YOUR FINISHING STUFF HERE, LIKE ADDING THE
                // LOADED IMAGES TO YOUR PAGE...
            }

        });
    }


    function addImageToLoadedImages(imageObj) {

         // YOU CAN DO OTHER STUFF HERE, LIKE CALCULATING
         // AND ADDING ADDITIONAL ATTRIBUTES TO THE IMAGE
         // ELEMENT

         // Add the image to the array of loaded images
         loadedFlickrImages.push(imageObj);

         // Increment counter for loaded images
         loadedFlickrImagesCounter++;


    }

});

我不能保证这段代码是“复制/粘贴准备好运行”,因为我已从更大的上下文中提取它,但我希望你能得到一般的想法。

答案 2 :(得分:0)

您可以使用API​​获取图像的大小而无需加载它们。您无需使用令牌进行身份验证,只需注册API密钥即可。获得密钥后,您可以执行以下操作来查看尺寸:

function getFlickrImageSize(photo_id, api_key){
    $.getJSON('http://api.flickr.com/services/rest/?method=' + 'flickr.photos.getsizes&api_key=' + api_key + '&photo_id=' + photo_id + '&format=json&jsoncallback=?',
        function(data){
            mySizeOj = data.sizes.size;
            // and in Firefox you can size the object result like..
            alert(mySizeOj.toSource());
        }
    );
}

答案 3 :(得分:0)

如果您在附加内容中执行图像尺寸请求,则会返回宽度和高度。

url_z个额外内容一样:

url_z="...." height_z="427" width_z="640"

你去了高度,没有额外的要求只是为了逐个获得尺寸。

在大多数情况下,您甚至不需要身份验证。