久しぶりに、プロフィールページを作成していきます。
プロフィールページ カテゴリーの記事一覧 - スマレジエンジニア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開発・写真)を繋げられるのは嬉しいことですね。