使用jQuery从Flickr获取图片高度而不加载图片文件?

3
我目前正在开发一个jQuery解决方案,其中我想从Flickr的RSS源加载图像。但是,我对来自源的默认大小不满意,我希望我加载的图像等于或高于我显示它们的包装器元素的高度。(宽度在这里不是问题。)
根据他们的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

这意味着没有保证的高度 - 我需要检查我想要加载的每个图像的高度。例如:如果一张图片是全景图并且我加载了大尺寸,那么高度可能仍然不足以填满我的包装器元素。这是因为最长的一边将是宽度,它将是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,就像这个链接

我希望能得到任何反馈!

先谢谢了!

4个回答

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


    }

});

我不能保证这段代码是“复制/粘贴即可运行”的,因为我将其从更大的上下文中提取出来,但我希望您能理解其一般思路。


1
也许我对问题的理解有误,但是也许可以在html中设置高度,然后通过jquery调整到最大的最佳大小?加载所有图像的最大实际大小会浪费资源,但这比多次加载图像要好。
对于html设置,只要记住最小可能的图像即可防止空白填充。当然,设置一个维度将允许另一个自动设置。如果裁剪是一个问题,一个技巧是设置包装器的大小并使用overflow:hidden。
对于jquery调整大小,考虑到图像不会立即加载,观看者很可能会看到图像改变大小,这并不理想。除非你将它们隐藏直到加载、调整大小,然后显示。

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());
        }
    );
}

事实是,我正在开发一个jQuery插件,希望尽可能简单易用。如果只是为了个人使用,我可以注册一个API密钥并按照您的建议操作,但这是为大众使用而设计的,我希望用户能够在不必注册API密钥的情况下加载图像。大多数用户甚至不知道什么是API。尽管如此,非常感谢您的建议! - tkahn

0

如果在额外请求中执行图像大小请求,则将返回宽度和高度。

例如url_z的额外返回:

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

这样您就可以获取高度,而无需额外请求逐个获取尺寸。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接