28

ユーザーが画像をアップロードしたり、テキストを追加したり、描画したりできる「画像ジェネレーター」を作成しています。出力される画像は固定サイズ(698x450)です。

クライアント側では、ユーザーが画像をアップロードすると、その画像は、background-size:coverで698x450のdivの背景として設定されます。これにより、領域がきれいに埋められます。

最終的に結合された画像は、GD関数を使用してPHPによって生成されます。私の質問は、CSSと同じようにPHPで画像を拡大縮小するにはどうすればよいかということです。PHPスクリプトの結果を、上記のように画像がCSSで設定されているかのように見せたいです。background-size:coverを使用しているブラウザが画像を適切に拡大縮小する方法を計算する方法を知っている人はいますか?これをPHPに変換したいと思います。

ありがとう

4

5 に答える 5

58

これがカバー計算の背後にあるロジックです。

4つの基本値があります:

imgWidth // your original img width
imgHeight

containerWidth // your container  width (here 698px)
containerHeight

これらの値から導き出された2つの比率:

imgRatio = (imgHeight / imgWidth)       // original img ratio
containerRatio = (containerHeight / containerWidth)     // container ratio

2つの新しい値を見つけたい:

finalWidth // the scaled img width
finalHeight

それで :

if (containerRatio > imgRatio) 
{
    finalHeight = containerHeight
    finalWidth = (containerHeight / imgRatio)
} 
else 
{
    finalWidth = containerWidth 
    finalHeight = (containerWidth / imgRatio)
}

...そしてあなたはbackground-size:coverに相当します。

于 2012-04-23T17:45:15.750 に答える
14

これは非常に古い質問ですが、私が書いた答えは、各画像自体ではなく、画像間の比率に最大値と最小値を使用することで、実際にはよりクリーンになります。

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)
  };
}

使用法

const { width, height } = getImageSize({
  container: {width: 100, height: 100},
  image: {width: 200, height: 50},
  size: 'cover' // 'contain' | 'auto' | '100% 100%'
});

遊び場

体系的に私が何を意味するのかを見てみたい場合は、jsbin ここに作成しました(この回答では必要ないと思った方法もありますが、通常以外の目的には非常に役立ちます)。scale

于 2016-08-24T19:31:36.317 に答える
4

私を正しい方向に向けてくれた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);
    }
于 2012-04-24T12:10:59.877 に答える
3

を使用するbackground-size: coverと、背景全体をカバーする最小サイズにスケーリングされます。

したがって、高さよりも薄い場合は、幅が面積と同じになるまで拡大縮小します。薄いよりも高い場合は、高さが面積と同じになるまで拡大縮小します。

カバーする領域よりも大きい場合は、収まるまで縮小します(高さのオーバーフローが少ない場合は、同じ高さまで拡大縮小し、幅のオーバーフローが少ない場合は、同じ幅になるまで縮小します)。

于 2012-04-23T17:42:54.067 に答える
3

ブラウザのサイズ変更とdivのアドホックな配置をサポートしながら、HTMLの背景画像と一致するようにdivの背景画像を拡大縮小して配置する方法を長い間探した後、このQAに出くわしました。これを思いつきました。

HTMLの背景に一致するように配置されたdivの背景画像

: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>

于 2021-03-16T18:02:25.280 に答える