如何从 srcset 确定最高分辨率图像

Tus*_*kla 5 javascript url jquery image srcset

假设我有一张图片

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


现在这也可以是这样的格式

<img srcset="large.jpg 2x, medium.jpg 1.3x, small.jpg 0.8x"
     sizes="(min-width: 700px) 700px, 100vw"
     alt="A woman reading">
Run Code Online (Sandbox Code Playgroud)


另外,(不是有效的 HTML)

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


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

我希望我能展示我已经尝试过的东西,但我没有想到如何做到这一点!

Sar*_*glt 5

这是我使用的:

static getHighestResImg(element) {
  if (element.getAttribute("srcset")) {
    return element
      .getAttribute("srcset")
      .split(",")
      .reduce(
        (acc, item) => {
          let [url, width] = item.trim().split(" ");
          width = parseInt(width);
          if (width > acc.width) return { width, url };
          return acc;
        },
        { width: 0, url: "" }
      ).url;
  }

  return element.getAttribute("src");
}
Run Code Online (Sandbox Code Playgroud)


Adr*_*tti 2

好吧,首先你的 HTML 代码是无效的,因为你不能混合xw的描述符srcset。选择其中之一,但不能同时选择两者。

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

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"));
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

您只需分割属性并忽略大小部分即可获取 URL srcset(我相信对正则表达式有更多了解的人可以做得更好):

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

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

这并不总是可以完成(可能是因为服务器不接受HEAD或由于压缩和/或宽高比而导致图像大小太相似),那么您必须解析 srcset属性。

2)让我们首先看一下您可以对像素密度描述符进行的操作的概念证明(读作:它不完整且高效)x:用空白空间进行分割.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

宽度描述符的情况有所不同,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 /sf/answers/45615251/
    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;
}
Run Code Online (Sandbox Code Playgroud)

现在您已经有了所需的大小(检查其单位并适当转换它,例如这篇文章),并且您已完成将其与从 中提取的宽度描述符一起使用srcset

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

var isPixelDensity = srcset.trim().substr(-1) === "x";
Run Code Online (Sandbox Code Playgroud)

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