如何从 srcset 中确定最高分辨率图像
how to determine highest resolution image from srcset
假设我有一个图像
<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
格式或两者都可以,我不知道如何区分这是否是 1200w
格式还是 2x
格式,即使我确实知道是什么,我如何比较它们以确定最大尺寸。
我希望我能展示我已经尝试过的东西,但我没有想到如何做到这一点!
嗯,首先你的 HTML 代码是无效的,因为你不能为 srcset
混合 x
和 w
描述符。选择一个,但不能同时选择两个。
1) 除非您全部下载它们,否则您无法知道哪个图像更大,当然您可以 - 当支持服务器端时 - 执行 HEAD
请求对于每个图像并检查 Content-Length
header 属性。这并不容易,你得到的只是以字节为单位的图像大小,而不是它的尺寸,但它是一个很好的近似值。大致是这样的:
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 中更容易 - 使用 queues 和 $(document).queue()
jQuery 方法顺序调用。
这不能总是完成(可能是因为服务器不接受 HEAD
或由于压缩 and/or 宽高比图像尺寸太相似)那么你必须 解析 srcset
属性。
2) 让我们先看看 概念验证 (读作:它不完整也没有效率)你可以做什么像素密度描述符 x
:用白色 space .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://whosebug.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
.[=34= 中提取的宽度描述符一起使用的操作]
请注意,除非下载,否则您不知道哪个图像更大。您可以假设更高的像素密度 x
或更高的宽度描述符 w
(但它 必须 是根据 sizes
属性内容计算的,更大的屏幕使用更大的图像)会给你更大的。当然这是一个假设,在某些情况下它可能会失败。要确定必须使用哪一个,只需:
var isPixelDensity = srcset.trim().substr(-1) === "x";
只需...将这些示例放在一起,处理遗漏的角落情况、基本错误处理和浏览器特定问题,您就完成了...
我需要对生成的相关 wordpress 图片执行相同的操作 srcset
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
更改为所需的目标 class)
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的新手,所以如果我走了更长的路,请原谅。 ;)
欢迎对代码进行任何添加/更新。
这是我使用的:
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");
}
假设我有一个图像
<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
格式或两者都可以,我不知道如何区分这是否是 1200w
格式还是 2x
格式,即使我确实知道是什么,我如何比较它们以确定最大尺寸。
我希望我能展示我已经尝试过的东西,但我没有想到如何做到这一点!
嗯,首先你的 HTML 代码是无效的,因为你不能为 srcset
混合 x
和 w
描述符。选择一个,但不能同时选择两个。
1) 除非您全部下载它们,否则您无法知道哪个图像更大,当然您可以 - 当支持服务器端时 - 执行 HEAD
请求对于每个图像并检查 Content-Length
header 属性。这并不容易,你得到的只是以字节为单位的图像大小,而不是它的尺寸,但它是一个很好的近似值。大致是这样的:
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 中更容易 - 使用 queues 和 $(document).queue()
jQuery 方法顺序调用。
这不能总是完成(可能是因为服务器不接受 HEAD
或由于压缩 and/or 宽高比图像尺寸太相似)那么你必须 解析 srcset
属性。
2) 让我们先看看 概念验证 (读作:它不完整也没有效率)你可以做什么像素密度描述符 x
:用白色 space .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://whosebug.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
.[=34= 中提取的宽度描述符一起使用的操作]
请注意,除非下载,否则您不知道哪个图像更大。您可以假设更高的像素密度 x
或更高的宽度描述符 w
(但它 必须 是根据 sizes
属性内容计算的,更大的屏幕使用更大的图像)会给你更大的。当然这是一个假设,在某些情况下它可能会失败。要确定必须使用哪一个,只需:
var isPixelDensity = srcset.trim().substr(-1) === "x";
只需...将这些示例放在一起,处理遗漏的角落情况、基本错误处理和浏览器特定问题,您就完成了...
我需要对生成的相关 wordpress 图片执行相同的操作 srcset
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
更改为所需的目标 class)
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的新手,所以如果我走了更长的路,请原谅。 ;)
欢迎对代码进行任何添加/更新。
这是我使用的:
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");
}