【JavaScript】写真の一覧表示を画面に合わせて最適な大きさにして全部表示したい

# はじめに

モニターの画面いっぱいに写真の一覧を表示したい！という思いがあり、記事にしてみました！

モニターの大きさって色々あるので固定値ではなく、画面の大きさによって写真の大きさが一番大きく出るようにしたいです。

20枚でも40枚でも画面いっぱいにスクロールなしで、写真を見れるようにします。


# 結論

```js:
  function optimalWidth(photoNum, aspectRatio, allWidth, allHeight) {
    var resultWidth = 0;
    for (let i = 1; i <= photoNum; i++) {
      var w = allWidth / i;
      var heightNum = Math.ceil(photoNum / i);
      var h = allHeight / heightNum;
      var aspectH = w * aspectRatio * heightNum;
      var widthFromeight = h / aspectRatio;
      var aspectW = widthFromeight * i;
      if (allHeight >= aspectH && w > resultWidth) {
        resultWidth = w;
      }
      if (allWidth >= aspectW && widthFromeight > resultWidth) {
        resultWidth = widthFromeight;
      }
    }
    return resultWidth;
  }
```

こんな感じで作成しました。（わかりづらくてすみません）

`optimalWidth`関数に

 第1引数:並ばせたい写真の数
 第2引数:表示させる領域の縦横比
 第3引数:写真を並ばせたい領域の横幅
 第4引数:写真を並ばせたい領域の縦幅

 をいれると、写真1枚の適切な横幅が返ってきます。

 例えば、縦幅500pxと横幅500pxの領域に 縦:横 = 9:16 で5枚の写真を置きたいとすると、以下のように呼び出します。

 ```js:
 var result = optimalWidth(5, 9/16, 500, 500);

 // result = 250 が返却される
 ```

 そうすると、その条件で一番写真が大きくなるような横幅が返ってきます。

 それを写真1つ1つに横幅と縦幅を設定してあげると、最大サイズで画面に並ばせることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/7156082c-f99d-44b9-e5f8-0dfd1e836960.png)


こんな感じです。（真ん中ぞろえとかにはしてないのでお好みで）

もう一つやってみます。

縦幅500pxと横幅600pxの領域に 縦:横 = 9:16 で5枚の写真を置きたいとすると、
 ```js:
 var result = optimalWidth(5, 9/16, 500, 500);

 // result = 296.2962962962963 が返却される
 ```
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/4fd55f5e-0bbc-5e96-8b66-1c4fb9bfbfaa.png)

 こんな感じになります。

# 画面の横幅が変わった時

ウィンドウのサイズが変化したときの状態を感知して写真の大きさを変えたいというときがあるかもしれません。

そのために、ウィンドウのサイズが変わった時を検知するには以下のようにするといいです。

```js
  var isPendding = false;
  function resizeWindow() {
    if (isPendding) {
      return;
    }
    isPendding = true;
    window.setTimeout(function () {
      isPendding = false;
    }, 50);
    console.log("サイズが変わりました");
  }
  window.addEventListener("resize", resizeWindow);
```
`isPendding`を用意したのは、画面サイズが変わるときに何度も関数が呼ばれてしまい、無駄な計算が走りまくってしまうので、0.05秒のクールタイムを設けています。

 # ソース

念のため作成したソースを全て載せておきます。

 ```html:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <title></title>
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body class="bg-gray-100 font-serif text-xl">
    <div
      id="all-area"
      class="w-[500px] h-[500px] flex flex-row flex-wrap bg-red-500"
    >
      <div class="js-photo-area bg-black border-white border"></div>
      <div class="js-photo-area bg-black border-white border"></div>
      <div class="js-photo-area bg-black border-white border"></div>
      <div class="js-photo-area bg-black border-white border"></div>
      <div class="js-photo-area bg-black border-white border"></div>
    </div>
    <script>
      function optimalWidth(photoNum, aspectRatio, allWidth, allHeight) {
        var resultWidth = 0;
        for (let i = 1; i <= photoNum; i++) {
          var w = allWidth / i;
          var heightNum = Math.ceil(photoNum / i);
          var h = allHeight / heightNum;
          var aspectH = w * aspectRatio * heightNum;
          var widthFromeight = h / aspectRatio;
          var aspectW = widthFromeight * i;
          if (allHeight >= aspectH && w > resultWidth) {
            resultWidth = w;
          }
          if (allWidth >= aspectW && widthFromeight > resultWidth) {
            resultWidth = widthFromeight;
          }
        }
        return resultWidth;
      }

      var photoNum = 5;
      var aspectRatio = 9 / 16;
      let allWidth = document.getElementById("all-area").clientWidth;
      let allHeight = document.getElementById("all-area").clientHeight;

      let optimalW = optimalWidth(photoNum, aspectRatio, allWidth, allHeight);

      var photoAreas = document.getElementsByClassName("js-photo-area");
      Array.from(photoAreas).forEach((photArea) => {
        console.log("s");
        photArea.style.width = optimalW + "px";
        photArea.style.height = optimalW * aspectRatio + "px";
      });

      var isPendding = false;
      function resizeWindow() {
        if (isPendding) {
          return;
        }
        isPendding = true;
        window.setTimeout(function () {
          isPendding = false;
        }, 50);
        console.log("サイズが変わりました");
      }
      window.addEventListener("resize", resizeWindow);
    </script>
  </body>
</html>
 ```


# さいごに

いろいろ見ずらいコードを書いてしまったと思います。

もしもっといい書き方を知っている方や、間違っているよというような指摘をしてくれる方がいましたら、教えていただけると助かります。

最後まで読んでいただきありがとうございました。