我正在创建一个“图像生成器”,用户可以上传图像并在其上添加文本和/或绘图。输出的图像是固定大小(698x450)。
在客户端,当用户上传他们的图像时,它被设置为具有背景大小:封面的698x450的div的背景。这使它很好地填补了这个区域。
最终的组合图像由PHP使用GD函数生成。我的问题是,如何在PHP中使用与在CSS中相同的方式来扩展图像。我希望PHP脚本的结果看起来像在CSS中设置图像一样。 有谁知道浏览器如何使用background-size:cover计算如何适当缩放图像?我想把它翻译成PHP。
由于
答案 0 :(得分:49)
这是封面计算背后的逻辑。
您有四个基本值:
imgWidth // your original img width
imgHeight
containerWidth // your container width (here 698px)
containerHeight
从这些值中得出两个比率:
imgRatio = (imgHeight / imgWidth) // original img ratio
containerRatio = (containerHeight / containerWidth) // container ratio
您想要找到两个新值:
finalWidth // the scaled img width
finalHeight
所以:
if (containerRatio > imgRatio)
{
finalHeight = containerHeight
finalWidth = (containerHeight / imgRatio)
}
else
{
finalWidth = containerWidth
finalHeight = (containerWidth / imgRatio)
}
...你有相当于背景大小:封面。
答案 1 :(得分:3)
使用background-size: cover
时,它会缩放到覆盖整个背景的最小尺寸。
因此,如果它比它高,那么将其缩放直到其宽度与该区域相同。如果它比它更薄,那么将它缩放到它的高度与面积相同。
当它大于要覆盖的区域时,向下缩放直到它适合(如果高度溢出较少,则缩放到相同的高度,如果宽度较小的溢出,则缩放直到相同的宽度)。 / p>
答案 2 :(得分:3)
感谢mdi让我指向正确的方向,但这似乎并不合适。 这是对我有用的解决方案:
$imgRatio = $imageHeight / $imageWidth;
$canvasRatio = $canvasHeight / $canvasWidth;
if ($canvasRatio > $imgRatio) {
$finalHeight = $canvasHeight;
$scale = $finalHeight / $imageHeight;
$finalWidth = round($imageWidth * $scale , 0);
} else {
$finalWidth = $canvasWidth;
$scale = $finalWidth / $imageWidth;
$finalHeight = round($imageHeight * $scale , 0);
}
答案 3 :(得分:3)
我知道这是一个非常古老的问题,但我写的答案实际上更清晰,通过在图像之间使用max和min来代替每个图像本身:
var originalRatios = {
width: containerWidth / imageNaturalWidth,
height: containerHeight / imageNaturalHeight
};
// formula for cover:
var coverRatio = Math.max(originalRatios.width, originalRatios.height);
// result:
var newImageWidth = imageNaturalWidth * coverRatio;
var newImageHeight = imageNaturalHeight * coverRatio;
我喜欢这种方法,因为它非常系统 - 也许它是错误的词 - 。我的意思是你可以摆脱if
语句并使其更符合数学公式"一种方式(输入=输出,如果这是有道理的):
var ratios = {
cover: function(wRatio, hRatio) {
return Math.max(wRatio, hRatio);
},
contain: function(wRatio, hRatio) {
return Math.min(wRatio, hRatio);
},
// original size
"auto": function() {
return 1;
},
// stretch
"100% 100%": function(wRatio, hRatio) {
return { width:wRatio, height:hRatio };
}
};
function getImageSize(options) {
if(!ratios[options.size]) {
throw new Error(options.size + " not found in ratios");
}
var r = ratios[options.size](
options.container.width / options.image.width,
options.container.height / options.image.height
);
return {
width: options.image.width * (r.width || r),
height: options.image.height * (r.height || r)
};
}
我想创建一个jsbin
here,如果你想看看我对系统的意思(它还有scale
方法我认为在这个答案中不需要,但对于通常的其他东西非常有用。
答案 4 :(得分:2)
经过长时间搜索如何在 div 上缩放和定位背景图像以匹配 html 背景图像,同时还支持浏览器调整大小和 div 的临时定位后,我偶然发现了这个 QA,我想出了这个。
:root {
/* background image size (source) */
--bgw: 1920;
--bgh: 1080;
/* projected background image size and position */
--bgscale: max(calc(100vh / var(--bgh)), calc(100vw / var(--bgw)));
--pbgw: calc(var(--bgw) * var(--bgscale)); /* projected width */
--pbgh: calc(var(--bgh) * var(--bgscale)); /* projected height */
--bgLeftOverflow: calc((var(--pbgw) - 100vw) / 2);
--bgTopOverflow: calc((var(--pbgh) - 100vh) / 2);
}
JS 等效
window.onresize = () => {
const vw100 = window.innerWidth
const vh100 = window.innerHeight
/* background image size (source) */
const bgw = 1920
const bgh = 1080
/* projected background image size and position */
const bgscale = Math.max(vh100 / bgh, vw100 / bgw)
const projectedWidth = bgw * bgscale | 0
const projectedHeight = bgh * bgscale | 0
const leftOverflow = (projectedWidth - vw100) / 2 | 0
const topOverflow = (projectedHeight - vh100) / 2 | 0
console.log(bgscale.toFixed(2), projectedWidth, projectedHeight, leftOverflow, topOverflow)
}
尝试使用此代码段调整窗口大小以查看结果。
最好在整页视图中查看。提示:打开控制台。
window.onresize = () => {
const vw100 = window.innerWidth
const vh100 = window.innerHeight
const bgw = 1920
const bgh = 1080
const bgscale = Math.max(vh100 / bgh, vw100 / bgw)
const projectedWidth = bgw * bgscale | 0
const projectedHeight = bgh * bgscale | 0
const leftOverflow = (projectedWidth - vw100) / 2 | 0
const topOverflow = (projectedHeight - vh100) / 2 | 0
console.log(bgscale.toFixed(2), projectedWidth, projectedHeight, leftOverflow, topOverflow)
}
:root {
/* background image size */
--bgurl: url('https://i.stack.imgur.com/3iy4y.jpg');
--bgw: 1000;
--bgh: 600;
--bgscale: max(calc(100vh / var(--bgh)), calc(100vw / var(--bgw)));
--pbgw: calc(var(--bgw) * var(--bgscale));
--pbgh: calc(var(--bgh) * var(--bgscale));
--bgLeftOverflow: calc((var(--pbgw) - 100vw) / 2);
--bgTopOverflow: calc((var(--pbgh) - 100vh) / 2);
}
html {
background: #000 var(--bgurl) no-repeat center center fixed;
background-size: cover;
overflow: hidden;
}
#panel {
--x: 100px;
--y: 100px;
--w: 200px;
--h: 150px;
position: absolute;
left: var( --x);
top: var( --y);
width: var(--w);
height: var(--h);
background-image: var(--bgurl);
background-repeat: no-repeat;
background-position: calc(0px - var(--bgLeftOverflow) - var(--x)) calc(0px - var(--bgTopOverflow) - var(--y));
background-size: calc(var( --bgscale) * var(--bgw));
filter: invert(1);
}
<div id="panel"></div>