1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

画像の枚数に応じてレイアウトを自動で変形するJavaScript処理

Last updated at Posted at 2022-07-22

この記事について

先日、インターンでの課題としてライブラリを作成しました。記事に残しておくと身になるという話をよく聞くので、作成した過程を書き残したいと思います。
筆者は駆け出しでありJavaScriptは勉強したてなので、アドバイスなどがあればお願いします!

ライブラリの概要

  • htmlのul要素に.js-photo-galleryというクラス名を付けるとli要素の画像がhttps://master.dxgxkh02xtdew.amplifyapp.com のようなレイアウトに自動で整形される
  • 同じ枚数でも、画像のアスペクト比に応じて異なるレイアウトになる
  • レイアウトはcssのGrid Layoutを使用する

レイアウトの作り方

css適用

下のサイトを参考にレイアウトを作成しました。
まず、好きな割合で区切りを決めると境目に番号が割り振られます(縦の線は左、横の線は上から1)。大きさをどの境からどの境までかで指定することで好きな形にできるという使い方でした。

レイアウトの枠組み

styles.css
ul.js-photo-gallery {
    margin-left: 0;
    padding-left: 0;
    width: 500px;
    height: 500px;
    grid-gap: var(--gridgap-size);
    list-style: none;
}

/*横長の2枚の場合*/
.layout-2-horizontal {
    display: grid;
    grid-template-rows: 50% 50%;
}

クラス名はlayout-枚数-形としました。
分割の指定方法として%とfrがありますが、形が崩れてしまうときがあったので変に使い分けています。

javascriptの処理

おおまかな処理の流れは
js-photo-galleryクラスのエレメントを取得→画像の形、枚数を取得→合うクラス名を付与

index.js
function run () {
  const elements = document.getElementsByClassName("js-photo-gallery");
  const elementsArray = Array.from(elements);
  elementsArray.forEach((elem) => {
    const shape = getImageShape(elem);
    var numberOfImages = elem.childElementCount;

    if (numberOfImages >= 6) {
      const li = elem.getElementsByTagName("li");
      setOverlayPosition(li);
      displayOverflowNumbers(elem, li);
      setHideClass(li);
      numberOfImages = "more";
    }

    elem.classList.add(`layout-${numberOfImages}-${shape}`);
    gridGapSize("5px");
  });
}

画像の形はただwidthとheightを比べるだけです。

index.js
function getImageShape(elem) {
    const imgs = elem.getElementsByTagName("img");
    if (imgs[0].width > imgs[0].height) {
      return shape = "horizontal";
    } else if (imgs[0].width < imgs[0].height) {
      return shape = "vertical";
    } else {
      return shape = "square";
    }
}

6枚以上の場合は下図のようにしたかったため、オーバーレイの処理を行っています。
image.png

index.js
/*5番目の画像に重ねるようにする*/
function setOverlayPosition(li) {
    li[4].classList.add("position");
    const newElement = document.createElement("div");
    newElement.classList.add("overlay");
    const parentLi = li[4];
    parentLi.insertBefore(newElement, parentLi.firstChild);
}
/*何枚の画像があるか見やすくする*/
function displayOverflowNumbers(elem, li) {
    const numberTextElement = document.createElement("p");
    const numberContent = document.createTextNode("+" + (li.length - 4));
    numberTextElement.appendChild(numberContent);
    numberTextElement.classList.add("more");

    const parentDiv = elem.getElementsByClassName("overlay");
    parentDiv[0].appendChild(numberTextElement);
}
/*6番目以降の画像は見えないようにする*/
function setHideClass(li) {
    liArray = Array.from(li);
    liArray.forEach((v, i) => {
        if (i >= 5) {
            v.classList.add("hide");
        }
    });
}

反省

DOMに依存しすぎている、アスペクト比の異なる複数の画像の場合に対応できないなど、完成度はまだまだ実用的ではないですが、一通り機能が完成してよかったです。
分からなくなったときに、検索能力の乏しさや自分の質問の曖昧さを感じたので、そういった基礎的な能力を身に付けたいと思いました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?