【问题标题】:how to determine highest resolution image from srcset如何从 srcset 确定最高分辨率的图像
【发布时间】:2016-08-01 05:07:37
【问题描述】:

假设我有一个图像

<img srcset="large.jpg 1400w, medium.jpg 700w, small.jpg 400w"
     sizes="(min-width: 700px) 700px, 100vw"
     alt="A woman reading">


现在这也可以是

之类的格式
<img srcset="large.jpg 2x, medium.jpg 1.3x, small.jpg 0.8x"
     sizes="(min-width: 700px) 700px, 100vw"
     alt="A woman reading">


另外,(不是有效的 HTML)

<img srcset="large.jpg 1400w, medium.jpg 1.3x, small.jpg 0.8x"
     sizes="(min-width: 700px) 700px, 100vw"
     alt="A woman reading">


现在我如何提取具有最高分辨率图像的 URL。
我想过拆分 srcset 然后提取大小,但问题是大小可以是 1200w 格式或 2x 格式或两者兼而有之,我不知道如何区分这是否是 @987654326 @ 格式或 2x 格式,即使我确实找出了什么是什么,我如何比较它们以确定最大尺寸。

我希望我能展示我尝试过的东西,但我对如何做到这一点一无所知!

【问题讨论】:

  • 这似乎是一个 XY 问题。为什么需要这个?
  • 另外,你为什么不能假设它是列表中的第一项?
  • @JanDvorak XY 问题??我必须在用户页面上注入一个脚本,然后在弹出窗口中分别向他显示页面上可用的图像。现在我可以简单地使用 SRC 但它会给我默认图像但是我想获得最好的图片。
  • @JanDvorak 第一个是否有必要成为最大的?
  • @JanDvorak 是否是 XY 问题无关紧要,只要问题明确即可。

标签: javascript jquery image url srcset


【解决方案1】:

首先,您的 HTML 代码无效,因为您不能将 xw 描述符混合用于 srcset。选择其中之一,但不要同时选择两者。

1) 除非您全部下载它们,否则您无法知道哪个图像更大,当然您可以 - 当支持服务器端时 - 对每个图像执行 HEAD 请求并检查 @987654328 @标头属性。这并不容易,你得到的只是图像大小(以字节为单位),而不是它的尺寸,但它是一个很好的近似值。大致是这样的:

var sizes = [];

// Peform this for each UR...
$.ajax({
    type: "HEAD",
    url: imageUrl,
    success: function(data, textStatus, request) {
        sizes.push({
            url: imageUrl,
            size: parseInt(request.getResponseHeader("Content-Length"));
        });
    }
});

您可以简单地拆分 srcset 属性并忽略大小部分来获取 URL(我相信对正则表达式有更好了解的人可以做得更好):

var urls = srcset.replace(/\s+[0-9]+(\.[0-9]+)?[wx]/g, "").split(/,/); 

调用可以并行完成,或者 - 更容易 IMO - 使用队列和 $(document).queue() jQuery 方法顺序完成。

这不能总是完成(可能是因为服务器不接受 HEAD 或者由于压缩和/或纵横比,图像大小太相似)然后你必须解析 @987654334 @ 属性。

2) 让我们首先看一个概念证明(读作:它不完整也不高效),您可以为像素密度描述符x 做些什么:split有超过空格.split(/ /),然后选择最大的。

// Read value from tag...this is just for testing
var srcset = "small.jpg 0.8x, large.jpg 1.5x, medium.jpg 1.3x";

var biggestImage = "";
var highestPixelDensity = 1;

for (var descriptor of srcset.split(/,/)) {
    var parts = descriptor.trim().split(/ /);

    // Here we check only for pixel density, see later for
    // width descriptor but code is straightforward
    var pixelDensity = parseFloat(parts[1].substring(-1));
    if (pixelDensity > highestPixelDensity) {
        biggestImage = parts[0];
        highestPixelDensity = pixelDensity;
    }
}

宽度描述符w 的情况有所不同,因为它与sizes 相关,那么您首先需要确定应用哪个。这有点复杂,但使用window.matchMedia() 很容易做到(同样它不是完整的代码,而是一个说明性的概念证明):

// Read this from tag...
var sizes = "(min-width: 800px) 700px, (min-width: 700px) 300px";

for (var descriptor of sizes.split(/,/)) {
    // Love this from https://stackoverflow.com/a/651646/1207195
    var imageSize = descriptor.split(/[, ]+/).pop();

    // You still need to handle last item special case (where there is not media query).
    var mediaQuery = descriptor.substring(-imageSize.length);

    // You can stop with first matched media query, you have your required imageSize
    var isMatch = window.matchMedia(mediaQuery).matches;
}

现在您已经获得了所需的大小(检查其单位并进行适当的转换,例如this post),并且您可以将其与从srcset 提取的宽度描述符一起使用。

请注意,除非您下载它,否则您不知道哪个图像更大。你可以假设更高的像素密度x或更高的宽度描述符w(但它必须根据sizes属性内容计算,更大的屏幕使用更大的图像)会给你较大的一个。当然这是一个假设,在某些情况下它可能会失败。要确定必须使用哪一个,只需:

var isPixelDensity = srcset.trim().substr(-1) === "x";

只需...将这些示例放在一起,处理丢失边角的情况、基本错误处理和浏览器特定问题,您就完成了...

【讨论】:

  • 非常感谢
    但是很抱歉我没有得到最后一行。我的理解是,如果我的屏幕尺寸与mediaQuery 匹配,那么这就是我需要的。如果我做对了,那么恐怕我不需要那个,但无论mediaQuery如何,我都需要最大/最大的图像。我该怎么做?
  • 你不知道确切图像大小,除非你全部下载它们,但你可以假设更大的图像将用于更大的屏幕(宽度...)然后当您有一个候选尺寸(来自 sizes 属性)时,您将选择具有更大宽度的那个(来自 srcset 属性)。对于宽度描述符,这些属性一起工作(但像素密度可以忽略大小)
  • 想知道您是否也可以帮助我this question...?
  • 让 DelightedD0D 有机会发布答案,但您可能想看看另一个问题:stackoverflow.com/q/4177803/1207195。不是那么容易,但没有扩展是可能的(除非你可以管理他们的部署并限制在 Chrome 中)
【解决方案2】:

这是我使用的:

 static getHighestResImg(element){
        if(element.getAttribute('srcset')){
            let highResImgUrl = '';
            let maxRes = 0;
            let imgWidth,urlWidthArr;
            element.getAttribute('srcset').split(',').forEach((item)=>{
                urlWidthArr = item.trim().split(' ');
                imgWidth = parseInt(urlWidthArr[1]);
                if(imgWidth > maxRes) {
                    maxRes = imgWidth;
                    highResImgUrl = urlWidthArr[0];
                }

            });

            return highResImgUrl;
        }else{
          return  element.getAttribute('src');
        }

    }

【讨论】:

    【解决方案3】:

    我需要对生成的和相关的 srcset 的 wordpress 图片做同样的事情

    Wordpress 创建srcset 的方式是先出现较小的图像,然后不断增加,直到在srcset 中获得最大的图像。

    wordpress 生成的示例图片代码:

    <img width="300" height="221" src="http://www.example.com/wp-content/uploads/2017/01/Sharon-Ron-Chip-300x221.jpg" class="vc_single_image-img attachment-medium" alt="" srcset="http://www.example.com/wp-content/uploads/2017/01/Sharon-Ron-Chip-300x221.jpg 300w, http://www.example.com/wp-content/uploads/2017/01/Sharon-Ron-Chip-768x566.jpg 768w, http://www.example.com/wp-content/uploads/2017/01/Sharon-Ron-Chip-1024x755.jpg 1024w" sizes="(max-width: 300px) 100vw, 300px">
    

    另外,在某些情况下,当图片太小时,wordpress 根本不会创建srcset 属性。

    所以,这就是我所做的:(将代码中的 my_image_class_to_target 更改为您所需的目标类)

    jQuery('img.my_image_class_to_target').each(function () {
        var mysrcset = jQuery(this).attr('srcset');
        if (typeof mysrcset !== 'undefined'){ //checking if the srcset attribute is defined
            lastsrcset = mysrcset.split(',');
            lastsrc = lastsrcset[(lastsrcset.length - 1)];
            lastpuresrc = lastsrc.split(' ');
            mysrc = lastpuresrc[1];
    
        } else { //when srcset is not defined in case of small images
        var mysrcset = jQuery(this).attr('src');
            mysrc = mysrcset;
        }
    
        // display or use src of biggest image src
        console.log(mysrc);
    
    });
    

    我是 Javascript/jQuery 的新手,所以如果我走了更长的路,请原谅。 ;)

    欢迎对代码进行任何添加/更新。

    【讨论】:

    • 当网址中有逗号时,这将失败,遗憾的是
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-20
    • 2020-09-08
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    相关资源
    最近更新 更多