以下是更新后的 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;
content: Rect;
positioned: Rect;
visible: Rect | null;
};
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),
};
};
您可以调整返回值,仅输出您需要的内容。
$('img.foo').outerWidth()
,您将获得元素的总计算宽度。不清楚您在询问什么。 - Marcos Pérez GudeouterWidth()
在这种情况下不起作用,因为它会导致“完整”图像的宽度 - 因此由于width:100%
而返回400
,而不是所需的150
。 - Chrisimg
元素生成的大小,然后使用naturalWidth
/naturalHeight
属性获取其宽高比,然后计算其渲染大小(基本上与您手动计算的方式相同)。 - Asons