对象拟合:获取结果尺寸
object-fit: get resulting dimensions
使用新的CSS功能object-fit
时,如何访问浏览器通过JavaScript选择的结果维度?
因此,让我们假设foo.jpg
是100x200像素。浏览器页面/视口宽400像素,高300像素。然后给出这个CSS代码:
img.foo {
width: 100%;
height: 100%;
object-fit: contain;
object-position: 25% 0;
}
浏览器现在会在最上面显示图像,正确的纵横比从左起第二个季度一直延伸到最下面。这导致了这些图像维度:
- 宽度:150px
- 高度:300px
- 左:62.5px
- 右:212.5px
那么,什么JavaScript调用(jQuery允许)会给我那些我手动计算的数字呢?(注意:JavaScript不知道CSS信息本身,因为用户可能会覆盖它们,甚至添加min-width
之类的内容)
为了使用我创建的小提琴代码:https://jsfiddle.net/sydeo244/
多亏了@bfred,我不必制作初始方法。
这里是他的扩展(和重写)版本,它也计算object-position
值。
function getRenderedSize(contains, cWidth, cHeight, width, height, pos){
var oRatio = width / height,
cRatio = cWidth / cHeight;
return function() {
if (contains ? (oRatio > cRatio) : (oRatio < cRatio)) {
this.width = cWidth;
this.height = cWidth / oRatio;
} else {
this.width = cHeight * oRatio;
this.height = cHeight;
}
this.left = (cWidth - this.width)*(pos/100);
this.right = this.width + this.left;
return this;
}.call({});
}
function getImgSizeInfo(img) {
var pos = window.getComputedStyle(img).getPropertyValue('object-position').split(' ');
return getRenderedSize(true,
img.width,
img.height,
img.naturalWidth,
img.naturalHeight,
parseInt(pos[0]));
}
document.querySelector('#foo').addEventListener('load', function(e) {
console.log(getImgSizeInfo(e.target));
});
#container {
width: 400px;
height: 300px;
border: 1px solid blue;
}
#foo {
width: 100%;
height: 100%;
object-fit: contain;
object-position: 25% 0;
}
<div id="container">
<img id="foo" src="http://dummyimage.com/100x200/000/fff.jpg"/>
</div>
旁注
似乎object-position
可以有两个以上的值,当需要调整(或添加)哪个参数返回左位置值时,
有一个名为intrinsic-scale
的npm包可以为您计算,但它不支持等效的object-position
:https://www.npmjs.com/package/intrinsic-scale
这是整个代码:
// adapted from: https://www.npmjs.com/package/intrinsic-scale
function getObjectFitSize(contains /* true = contain, false = cover */, containerWidth, containerHeight, width, height){
var doRatio = width / height;
var cRatio = containerWidth / containerHeight;
var targetWidth = 0;
var targetHeight = 0;
var test = contains ? (doRatio > cRatio) : (doRatio < cRatio);
if (test) {
targetWidth = containerWidth;
targetHeight = targetWidth / doRatio;
} else {
targetHeight = containerHeight;
targetWidth = targetHeight * doRatio;
}
return {
width: targetWidth,
height: targetHeight,
x: (containerWidth - targetWidth) / 2,
y: (containerHeight - targetHeight) / 2
};
}
其用法是:
getObjectFitSize(true, img.width, img.height, img.naturalWidth, img.naturalHeight);
这里有一个经过测试的更全面的算法,用于确定图像在屏幕上的显示方式。
var imageComputedStyle = window.getComputedStyle(image);
var imageObjectFit = imageComputedStyle.getPropertyValue("object-fit");
coordinates = {};
var imagePositions = imageComputedStyle.getPropertyValue("object-position").split(" ");
var horizontalPercentage = parseInt(imagePositions[0]) / 100;
var verticalPercentage = parseInt(imagePositions[1]) / 100;
var naturalRatio = image.naturalWidth / image.naturalHeight;
var visibleRatio = image.width / image.height;
if (imageObjectFit === "none")
{
coordinates.sourceWidth = image.width;
coordinates.sourceHeight = image.height;
coordinates.sourceX = (image.naturalWidth - image.width) * horizontalPercentage;
coordinates.sourceY = (image.naturalHeight - image.height) * verticalPercentage;
coordinates.destinationWidthPercentage = 1;
coordinates.destinationHeightPercentage = 1;
coordinates.destinationXPercentage = 0;
coordinates.destinationYPercentage = 0;
}
else if (imageObjectFit === "contain" || imageObjectFit === "scale-down")
{
// TODO: handle the "scale-down" appropriately, once its meaning will be clear
coordinates.sourceWidth = image.naturalWidth;
coordinates.sourceHeight = image.naturalHeight;
coordinates.sourceX = 0;
coordinates.sourceY = 0;
if (naturalRatio > visibleRatio)
{
coordinates.destinationWidthPercentage = 1;
coordinates.destinationHeightPercentage = (image.naturalHeight / image.height) / (image.naturalWidth / image.width);
coordinates.destinationXPercentage = 0;
coordinates.destinationYPercentage = (1 - coordinates.destinationHeightPercentage) * verticalPercentage;
}
else
{
coordinates.destinationWidthPercentage = (image.naturalWidth / image.width) / (image.naturalHeight / image.height);
coordinates.destinationHeightPercentage = 1;
coordinates.destinationXPercentage = (1 - coordinates.destinationWidthPercentage) * horizontalPercentage;
coordinates.destinationYPercentage = 0;
}
}
else if (imageObjectFit === "cover")
{
if (naturalRatio > visibleRatio)
{
coordinates.sourceWidth = image.naturalHeight * visibleRatio;
coordinates.sourceHeight = image.naturalHeight;
coordinates.sourceX = (image.naturalWidth - coordinates.sourceWidth) * horizontalPercentage;
coordinates.sourceY = 0;
}
else
{
coordinates.sourceWidth = image.naturalWidth;
coordinates.sourceHeight = image.naturalWidth / visibleRatio;
coordinates.sourceX = 0;
coordinates.sourceY = (image.naturalHeight - coordinates.sourceHeight) * verticalPercentage;
}
coordinates.destinationWidthPercentage = 1;
coordinates.destinationHeightPercentage = 1;
coordinates.destinationXPercentage = 0;
coordinates.destinationYPercentage = 0;
}
else
{
if (imageObjectFit !== "fill")
{
console.error("unexpected 'object-fit' attribute with value '" + imageObjectFit + "' relative to");
}
coordinates.sourceWidth = image.naturalWidth;
coordinates.sourceHeight = image.naturalHeight;
coordinates.sourceX = 0;
coordinates.sourceY = 0;
coordinates.destinationWidthPercentage = 1;
coordinates.destinationHeightPercentage = 1;
coordinates.destinationXPercentage = 0;
coordinates.destinationYPercentage = 0;
}
其中image
是HTML <img>
元素,coordinates
包含以下属性,假设我们认为sourceFrame
是图像完全打印时定义的矩形,即其自然尺寸,printFrame
是实际显示的区域,即printFrame.width = image.width
和printFrame.height = image.height
:
- CCD_ 15:CCD_
- CCD_ 17:CCD_
- CCD_ 19:CCD_
- CCD_ 21:CCD_
destinationXPercentage
:将打印图像的printFrame
上左上点的水平位置相对于printFrame
宽度的百分比destinationYPercentage
:将打印图像的printFrame
上左上点的垂直位置相对于printFrame
高度的百分比destinationWidthPercentage
:将在其上打印图像的printFrame
宽度相对于printFrame
宽度的百分比destinationHeightPercentage
:将在其上打印图像的printFrame
高度相对于printFrame
高度的百分比
很抱歉,scale-down
案件没有得到处理,因为它的定义不太清楚。
下面是一段更新的TypeScript代码,它处理所有值,包括object-fit: scale-down
和object-position
,它们都具有相对值、绝对值和关键字值:
type Rect = {
x: number;
y: number;
width: number;
height: number;
};
const dom2rect = (rect: DOMRect): Rect => {
const { x, y, width, height } = rect;
return { x, y, width, height };
};
const intersectRects = (a: Rect, b: Rect): Rect | null => {
const x = Math.max(a.x, b.x);
const y = Math.max(a.y, b.y);
const width = Math.min(a.x + a.width, b.x + b.width) - x;
const height = Math.min(a.y + a.height, b.y + b.height) - y;
if (width <= 0 || height <= 0) return null;
return { x, y, width, height };
};
type ObjectRects = {
container: Rect; // client-space size of container element
content: Rect; // natural size of content
positioned: Rect; // scaled rect of content relative to container element (may overlap out of container)
visible: Rect | null; // intersection of container & positioned rect
};
const parsePos = (str: string, ref: number): number => {
switch (str) {
case "left":
case "top":
return 0;
case "center":
return ref / 2;
case "right":
case "bottom":
return ref;
default:
const num = parseFloat(str);
if (str.endsWith("%")) return (num / 100) * ref;
else if (str.endsWith("px")) return num;
else
throw new Error(`unexpected unit object-position unit/value: '${str}'`);
}
};
const getObjectRects = (
image: HTMLImageElement | HTMLVideoElement
): ObjectRects => {
const style = window.getComputedStyle(image);
const objectFit = style.getPropertyValue("object-fit");
const naturalWidth =
image instanceof HTMLImageElement ? image.naturalWidth : image.videoWidth;
const naturalHeight =
image instanceof HTMLImageElement ? image.naturalHeight : image.videoHeight;
const content = { x: 0, y: 0, width: naturalWidth, height: naturalHeight };
const container = dom2rect(image.getBoundingClientRect());
let scaleX = 1;
let scaleY = 1;
switch (objectFit) {
case "none":
break;
case "fill":
scaleX = container.width / naturalWidth;
scaleY = container.height / naturalHeight;
break;
case "contain":
case "scale-down": {
let scale = Math.min(
container.width / naturalWidth,
container.height / naturalHeight
);
if (objectFit === "scale-down") scale = Math.min(1, scale);
scaleX = scale;
scaleY = scale;
break;
}
case "cover": {
const scale = Math.max(
container.width / naturalWidth,
container.height / naturalHeight
);
scaleX = scale;
scaleY = scale;
break;
}
default:
throw new Error(`unexpected 'object-fit' value ${objectFit}`);
}
const positioned = {
x: 0,
y: 0,
width: naturalWidth * scaleX,
height: naturalHeight * scaleY,
};
const objectPos = style.getPropertyValue("object-position").split(" ");
positioned.x = parsePos(objectPos[0], container.width - positioned.width);
positioned.y = parsePos(objectPos[1], container.height - positioned.height);
const containerInner = { x: 0, y: 0, width: container.width, height: container.height };
return {
container,
content,
positioned,
visible: intersectRects(containerInner, positioned),
};
};
您可以调整返回值以仅输出您需要的内容。
- 这是使用html快照和谷歌获取的预期结果吗?SEO/SPA
- jQuery使用api获取typeform结果
- 在foreach中获取ajax结果
- 对象拟合:获取结果尺寸
- Mongodb$in以与数组中相同的顺序获取结果
- 从重复的javascript数组结果集中只获取一行
- 轮询:获取请求直到结果合适
- 获取在表单/文本字段中显示的结果
- 获取json结果的身份验证问题
- 将敲除绑定应用于模板,并将结果作为字符串获取
- 无法使用streams/highland.js从mongodb的结果中获取数据
- 如何将mysql查询的结果获取到html文本框中
- 获取结果未定义(主干.js)
- AngularJS:如何获取$http结果作为函数的返回值
- 无法从IE中的data.responseText获取结果,但在其他浏览器中工作
- Json 结果获取值
- 从动态创建的数据进行计算的结果获取 NaN
- JSON 字符串化结果获取特定键的值
- 如何在promise解析时手动将promise的结果获取到作用域变量中
- 根据搜索结果获取Flickr图片