画像を外接リサイズするコンポーネントをVueで実装

下記のように、画像を決まったサイズ（今回であれば正方形）で表示させたいときのtipsです。
サーバー側で画像を生成するのではなく、どんな画像サイズがくるか分からない状況でフロント側で実装する場合を想定しています。

![スクリーンショット 2019-05-17 17.14.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239038/f14f5b3b-d6b1-10b4-424b-caf84d9696a1.png)
引用：[【楽天市場】和菓子（スイーツ・お菓子）の通販](https://www.rakuten.co.jp/category/509708/?l-id=top_normal_gmenu_d_sweets_002)


![スクリーンショット 2019-05-17 16.59.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239038/8e042337-31aa-7dcc-3465-c3ed21765b31.png)

上記のような横長の画像を正方形にしたい場合、こうなります。

```sample.css
/* 通常 */
.sample__img {
  width: 400px;
  height: 400px;
}
/* 外接リサイズ */
.sample__fit-img {
  width: 400px;
  height: 400px;
  object-fit: cover;
}
```

![スクリーンショット 2019-05-17 17.18.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239038/69bf026f-574a-edb4-591e-fcc0155f3969.png)

widthとheightを指定しただけでは、画像がゆがんでしまいますね・・
上記のように `object-fit: cover` をすると一発で外接リサイズが実現します。

ただ、対応しているブラウザが一部になります。

![スクリーンショット 2019-05-16 18.35.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239038/beecf398-2f88-8ae3-008a-e881811ea211.png)

もっとブラウザ対応させたい！というときは `background-size: cover` を使います。

![スクリーンショット 2019-05-16 18.35.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239038/caae83cb-2359-80cb-5bcc-1052db916c62.png)

```sample.html
<div class="sample__fit-img"></div>
```
```sample.css
.sample__fit-img {
  background-image: url(https://cdn.pixabay.com/photo/2019/05/12/20/45/cat-4199084_960_720.jpg)
  background-size: cover; /* 外接リサイズ */
  background-repeat: no-repeat; /* リピートするか */
  background-position: center; /* 位置 */
}
```

ちなみに上記の実装だと背景画像とみなされるので
印刷しようと思っても表示されないので注意。ブラウザ対応をとるか、どっちかですね・・！

こちらで同じような議論がされていて面白かったです。
* [How do I prevent the error "Index signature of object type implicitly has an 'any' type" when compiling typescript with noImplicitAny flag enabled? - Stack Overflow](https://stackoverflow.com/questions/32968332/how-do-i-prevent-the-error-index-signature-of-object-type-implicitly-has-an-an)

## おまけ（VueでIE対応可能な外接リサイズ用のコンポーネントを作る）

```ObjectFitImg.vue
<template>
  <div :style="style" class="object-fit-img">
    <span v-if="alt" class="object-fit-img__alt">{{ alt }}</span>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';

interface ObjectFitStyle {
  width: string;
  height: string;
  'background-image': string;
  [key: string]: string | null;
}

@Component
export default class ObjectFitImg extends Vue {
  @Prop({ required: true }) readonly src!: string;
  @Prop({ required: true }) readonly alt!: string;
  @Prop({ default: null }) readonly width!: string;
  @Prop({ default: null }) readonly height!: string;

  get style(): ObjectFitStyle {
    const style: ObjectFitStyle = {
      width: '',
      height: '',
      'background-image': ''
    };

    style.width = this.width ? `${this.width}px` : '';
    style.height = this.height ? `${this.height}px` : '';
    style['background-image'] = `url(${this.src})`;

    return style;
  }
}
</script>

<style lang="scss" scoped>
.object-fit-img {
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;

  &__alt {
    visibility: hidden;
  }
}
</style>
```

ここまで書いてなんですが、個人的にはIEを捨てて `object-fit: cover` でいい気がします笑