Inspire - Capo Productions
等比缩放适配容器
推导
设:
- 容器尺寸为 (containerWidth, containerHeight)
- 图片原始尺寸为 (imgWidth, imgHeight)
- 缩放倍数为 。等比缩放后图片尺寸为 。
要求“图片完整放入容器且不裁剪”,也就是:
从不等式解出 的上界:
因此 必须同时小于等于这两个数,所以 允许的最大缩放值(也就是我们通常想取的,使图片尽可能大但仍然完整显示)就是这两个上界中的较小者:
直观解释:两个比值分别表示「在只受宽度限制时能放多大」和「在只受高度限制时能放多大」。要同时满足宽和高这两个限制,必须取两者都允许的规模 —— 也就是较小的那个。
留白方向
令
- 若 :取 ,宽度被“刚好撑满”,高度小于容器 ⇒ 上下留白(垂直居中)。
- 若 :取 ,高度被“刚好撑满”,宽度小于容器 ⇒ 左右留白(水平居中)。
- 若相等:恰好铺满,无留白。
额外说明
- 如果你不允许放大(只缩小),可以把结果限定为
s = min(1, min(r_w, r_h))
。 - 如果允许放大(例如把小图放大填满容器),就直接用上面的公式即可(可能 )。
JS 函数
js
function fitImage(containerWidth, containerHeight, imgWidth, imgHeight, allowUpscale = true) {
const rw = containerWidth / imgWidth
const rh = containerHeight / imgHeight
let scale = Math.min(rw, rh)
if (!allowUpscale)
scale = Math.min(1, scale)
let mode
if (Math.abs(rw - rh) < 1e-9)
mode = 'none' // 刚好铺满
else if (rw < rh)
mode = 'vertical-letterbox' // 上下留白(垂直居中)
else mode = 'horizontal-letterbox' // 左右留白(水平居中)
return { scale, mode, renderedWidth: imgWidth * scale, renderedHeight: imgHeight * scale }
}
示例
容器 800×600
,图片 1600×1000
:
结果:图片宽度刚好 800,高度变为 500 ⇒ 上下留白。