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

时间:2023-01-08 21:21:02

I'm currently working on a jQuery solution where I want to load images from a Flickr RSS-feed. I'm not satisfied with the default size I get from the feed though - I want the images I load to be equal to or higher than the height of the wrapper element I'm displaying them in. (Width is not a problem here.)

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

According to their API documentation, Flickr has an image size system that looks like this:

根据他们的API文档,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

This means that there is no guaranteed height - I need to check the height for each image I want to load. An example: if an image is a panorama and I load the large size, the height is probably still not enough to fill out my wrapper element. This is because the longest side will be the width and it will be 1024.

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

To complicate things, the height of the wrapper can vary - not dynamically after the page has loaded, but from page to page. On some pages it's 300 pixels, on others it's 100 pixels and so on.

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

As far as I understand the only way to get the height of an image file is to actually load it. So I have written some recursive code that loads an image, look's at its height and if it's not sufficient it calls itself again to load the next size. In the current version it starts with the smallest size and works its way up until it finds a suitable image or the biggest image possible.

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

Here's the code:

这是代码:

$.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;
               }
            });
        }
});

It's a litte rough around the edges, but I hope you get the picture.

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

This works, but it just seems so wasteful to have to load so many versions of an image just to get the right size?

这是有效的,但是为了获得合适的尺寸而必须加载这么多版本的图像似乎很浪费?

Do you have any suggestions for improvements? I'm thinking that it should start by making a qualified guess at which could be the best size and load it first. Then it would see if it fits or if it's too small or too big and load the next or previous image on the size scale. That way you could reduce the amount of images to load just to get the right size.

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

Even better: is there a way to find out the image sizes without loading the actual image files? Remember that I don't have access to the complete Flickr API - I'm just accessing a JSON-feed, like this one.

更好的是:有没有办法找出图像大小而不加载实际的图像文件?请记住,我无法访问完整的Flickr API - 我只是访问JSON-feed,就像这样。

I'd appreciate any feedback!

我很感激任何反馈!

Thanks in advance!

提前致谢!

4 个解决方案

#1


1  

Maybe I'm understanding the problem wrong, but maybe setting the height in html, then resizing via jquery to the largest optimal size? Loading the largest realistic size of all the images would be a waste, but it's better than loading an image more than once.

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

For the html setting, as long as it keeps in mind the smallest possible image to prevent blank padding. And of course setting one dimension would allow the other to set itself. And if cropping is an issue, one hack is to set the size of the wrapper and overflow:hidden.

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

For the jquery resizing, given that the images won't load instantly, chances are that the viewer will see the images change size which isn't ideal. Unless you kept them hidden until loaded, sized, then displayed.

对于jquery调整大小,考虑到图像不会立即加载,观看者可能会看到图像改变大小并不理想。除非你将它们隐藏起来,直到加载,调整尺寸,然后显示。

#2


1  

I've solved this by first making a qualified guess as to which image size might be the best one. This guess is based on the height of the element inside which the loaded images will be put. Then I load this plausible image size to see if it's tall enough. If it's taller than or equal to the desired height, I use it. Otherwise I load the next bigger size, check its height and so on.

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

Even though this probably means that I will be loading a larger amount of images compared to just loading the biggest size first I think that it's cheaper when it comes to the total amount of kilobytes loaded. Some preliminary tests show that from a standard feed of 20 Flickr images, 1 or 2 images need to be reloaded after the first load.

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

Let me know if you put this solution to the test and end up with a different result or think than my approach is wrong. I'm looking for the cheapest and best solution.

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

Here's the current code if anyone is interested:

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

$.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++;


    }

});

I can't guarantee that this code is "copy/paste ready to run" since I've extracted it from a bigger context, but I hope you get the general idea.

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

#3


0  

You can get the sizes of an image without loading them by using the API. You don't need to authenticate with a token, just register for an API key. Once you have your key you can do something like this to view sizes:

您可以使用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());
        }
    );
}

#4


0  

If you do an image size request in the extras, the width and height are returned.

如果在附加项中执行图像大小请求,则返回宽度和高度。

Like url_z extras return:

像url_z extras返回:

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

url_z =“....”height_z =“427”width_z =“640”

There you go with the height, without an additional request just to get the dimensions one by one.

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

You don't even need authentication in most cases.

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

#1


1  

Maybe I'm understanding the problem wrong, but maybe setting the height in html, then resizing via jquery to the largest optimal size? Loading the largest realistic size of all the images would be a waste, but it's better than loading an image more than once.

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

For the html setting, as long as it keeps in mind the smallest possible image to prevent blank padding. And of course setting one dimension would allow the other to set itself. And if cropping is an issue, one hack is to set the size of the wrapper and overflow:hidden.

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

For the jquery resizing, given that the images won't load instantly, chances are that the viewer will see the images change size which isn't ideal. Unless you kept them hidden until loaded, sized, then displayed.

对于jquery调整大小,考虑到图像不会立即加载,观看者可能会看到图像改变大小并不理想。除非你将它们隐藏起来,直到加载,调整尺寸,然后显示。

#2


1  

I've solved this by first making a qualified guess as to which image size might be the best one. This guess is based on the height of the element inside which the loaded images will be put. Then I load this plausible image size to see if it's tall enough. If it's taller than or equal to the desired height, I use it. Otherwise I load the next bigger size, check its height and so on.

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

Even though this probably means that I will be loading a larger amount of images compared to just loading the biggest size first I think that it's cheaper when it comes to the total amount of kilobytes loaded. Some preliminary tests show that from a standard feed of 20 Flickr images, 1 or 2 images need to be reloaded after the first load.

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

Let me know if you put this solution to the test and end up with a different result or think than my approach is wrong. I'm looking for the cheapest and best solution.

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

Here's the current code if anyone is interested:

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

$.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++;


    }

});

I can't guarantee that this code is "copy/paste ready to run" since I've extracted it from a bigger context, but I hope you get the general idea.

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

#3


0  

You can get the sizes of an image without loading them by using the API. You don't need to authenticate with a token, just register for an API key. Once you have your key you can do something like this to view sizes:

您可以使用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());
        }
    );
}

#4


0  

If you do an image size request in the extras, the width and height are returned.

如果在附加项中执行图像大小请求,则返回宽度和高度。

Like url_z extras return:

像url_z extras返回:

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

url_z =“....”height_z =“427”width_z =“640”

There you go with the height, without an additional request just to get the dimensions one by one.

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

You don't even need authentication in most cases.

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