スマレジエンジニアyushiのブログ

スマレジエンジニアのブログ

【プロフィールページ改修 第10回】写真セクションの追加

久しぶりに、プロフィールページを作成していきます。

プロフィールページ カテゴリーの記事一覧 - スマレジエンジニアyushiのブログ

技術スタックは下記の通りです。

  • nuxt.js
  • SCSS
  • Tailwind CSS

今回は、写真セクションを追加します。

写真

最近ミラーレスカメラを購入し、近所や出先で写真を撮っています。

まだまだ初心者なものの、せっかく撮影しているのでこれをプロフィールページに追加してみようと思います。

スクショ

完成品のスクリーンショットです。

一覧表示

追加したセクションです。

写真を一覧表示しています。ブラウザの幅に応じて、列数が1〜3の間で変化します。

拡大表示

一覧の画像をクリックすると、拡大表示します。
fadeのアニメーションも付与しています。

写真表示用コンポーネント

写真表示用のコンポーネントを追加します。

(LightBox.vue)

<template>
  <transition name="fade">
    <div
      v-if="filePath"
      class="light-box flex justify-center items-center"
      @click="$emit('close')"
    >
      <img class="image" :src="filePath" />
    </div>
  </transition>
</template>

<script>
export default {
  props: {
    filePath: {
      type: String,
      default: '',
    },
  },
}
</script>

<style lang="scss" scoped>
.light-box {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  z-index: 10000;
  background-color: #000;
  cursor: pointer;
}
.image {
  width: 90%;
  height: 90%;
  object-fit: contain;
}
.fade-enter-active {
  transition: all 0.5s ease;
}
.fade-leave-active {
  transition: all 0.5s ease;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>

filePathに値がある場合は画面を表示し、親コンポーネントにてfilePathがNullなれば、画面を閉じます。

画面を開く時・閉じるときにはfadeのアニメーションを行います。

参考: https://v2.vuejs.org/v2/guide/transitions.html

画面のどこかをクリックすると、親コンポーネントにイベントを発火し、親コンポーネントにてfilePathをNullにする想定です。

写真セクションコンポーネント

親のコンポーネントでは、単に画像を一覧表示します。

(PhotoSection.vue)

<template>
  <section id="photo">
    <div class="app-container">
      <h2 id="photos" class="section-title">PHOTOS</h2>
      <ul class="flex flex-row flex-wrap justify-between">
        <li v-for="photo in photos" :key="photo" class="photo-card">
          <img :src="'photos/' + photo" @click="select(photo)" />
        </li>
      </ul>
    </div>
    <LightBox :file-path="selectedPath" @close="clearSelection" />
  </section>
</template>

<script>
import LightBox from '../parts/LightBox.vue'

export default {
  components: {
    LightBox,
  },
  data() {
    return {
      selected: null,
    }
  },
  computed: {
    photos() {
      return [
        // ファイルパス一覧
      ]
    },
    selectedPath() {
      return this.selected ? 'photos/' + this.selected : ''
    },
  },
  methods: {
    select(target) {
      this.selected = target
    },
    clearSelection() {
      this.selected = null
    },
  },
}
</script>

<style lang="scss" scoped>
.photo-card {
  width: calc(33% - 5px);
  margin-bottom: 30px;
  cursor: pointer;
  transition: 0.2s;

  &:hover {
    filter: brightness(80%);
  }

  @media (max-width: $tablet-max-width) {
    width: calc(50% - 5px);
  }

  @media (max-width: $mobile-max-width) {
    width: 100%;
  }
}
</style>

flexboxとmedia queryを用いてで1〜3列で表示するように調整します。

写真選択時の選択状態管理や、写真表示用コンポーネントへのデータの受け渡し・イベントの受け取りを行います。

Pull Request

https://github.com/nek0meshi/profile/pull/20

あとがき

自分の持っている複数の要素(Web開発・写真)を繋げられるのは嬉しいことですね。