JQ Engineer Blog

Pain is temporary. It may last a minute, or an hour, or a day, or a year, but eventually it will subside and something else will take its place. If I quit, however, it lasts forever.

画像の中心を正方形にトリミングするJavascript

正確にはトリミングしたように見せるスクリプトです。 必要となった要件は以下の通り。

  • 横長、縦長画像に対応させる
    • 横長の場合は、左右は中心位置を取り、上下は目一杯表示する
    • 縦長の場合は、その逆
  • 指定のclassを付けるだけで動く
    • 複数の画面で動かす予定があったため、発火条件を単純にする

まず、htmlの準備をします。

1
2
3
4
5
<body>
  <div class="photo">
      <img class="trimImg" src="xxx.jpg">
  </div>
</body>

要点としては、トリミングしたいimgを囲うdivを用意することのみです。 正方形にする画像は.trimImgが付いているものです。 次に、css。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.photo {
  position:relative;
  overflow: hidden;
}

.photo img{
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}
.img-responsive {
  display: block;
  max-width: 100%;
  height: auto;
}

imgはposition:absoluteにして、親要素をposition:relativeにすることで様々な場所で使いやすくかと思います。 imgがposition:absoluteなのは、中心位置を取るためです。 最後にjsです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$(function(){
  function GetImageSize(){
    $('.trimImg').load(function(){
      target = $(this);
      parentwidth = target.parent().width();
      parentheight = target.parent().height();
      target.parent().css("height",parentwidth);
      targetwidth = target.width();
      targetheight = target.height();
      if(targetheight < targetwidth){
        targetleft = -(targetwidth/targetheight*parentwidth-parentwidth)/2;
        target.css({
          height: parentwidth,
          width: "auto",
          left: targetleft
        });
      } else if(targetheight > targetwidth){
        targettop = -(targetheight/targetwidth*parentheight-parentheight)/2;
        target.css({
          height: "auto",
          width: parentheight,
          top: targettop
        });
      } else {
        target.addClass('img-responsive');
      }
      });
  }
  GetImageSize();
});

流れとしては、

  1. htmlで指定した.trimImgを取得
  2. 画像自体と親要素の高さ、幅を取得
  3. 画像の高さと幅を比較して、横長か縦長か画像の形を判別
  4. 画像の形に合わせて、中心位置を計算
  5. 画像にスタイルを当てる

といったことをしています。 また、高さと幅が同じ場合には別のクラスを付けています。(bootstrapのものそのままです)

最初の部分で.load()を使い、画像読み込みが完了するのを待たせることで 高さや幅の取得ミスを防止しているのが、ほんの少しの工夫です。

以上