LoginSignup
9
7

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-05-17

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

スクリーンショット 2019-05-17 17.14.19.png
引用:【楽天市場】和菓子(スイーツ・お菓子)の通販

スクリーンショット 2019-05-17 16.59.58.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

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

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

スクリーンショット 2019-05-16 18.35.43.png

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

スクリーンショット 2019-05-16 18.35.37.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

おまけ(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 でいい気がします笑

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