<template> <div class="gallery-page" :class="{'is-mounted': isMounted }" > <GalleryImageViewer class="image-viewer" ref="imageViewer" :is-visible="imageViewerIsVisible" :image-url="viewingImageUrl" :has-next="activeImageIndex < galleries[activeGalleryIndex].images.length - 1" :has-prev="activeImageIndex > 0" @clickPrev="handleClickPrev" @clickNext="handleClickNext" @close="imageViewerIsVisible = false" /> <article class="gallery"> <h1 class="page-heading page-title"><span class="shadow-deco">{{ title }}</span></h1> <GalleryFeatured class="gallery__featured load-transition load-transition--1" :galleries="galleries" :gallery-active="activeGalleryIndex" @clicked="handleFeaturedClick" /> <GalleryThumbs class="gallery__thumbs load-transition load-transition--2" :featured-height="featuredImageHeight" :galleries="galleries" :active-row="activeRow" :active-index="activeImageIndex" :show-image="showImage" @thumbClick="handleThumbClick"/> </article> </div> </template> <script> import GalleryFeatured from '@/components/GalleryFeatured' import GalleryThumbs from '@/components/GalleryThumbs' import GalleryImageViewer from '@/components/GalleryImageViewer' export default { components: { GalleryFeatured, GalleryThumbs, GalleryImageViewer, }, props: { galleries: { type: Array, required: true }, title: { type: String, required: false, default () { return 'My Galleries' }, } }, data () { return { isMounted: false, featuredImageHeight: '16rem', imageViewerIsVisible: false, activeRow: 0, activeGalleryIndex: 0, activeImageIndex: 0, showImage: 0, } }, computed: { viewingImageUrl () { if ( this.galleries[this.activeGalleryIndex] && this.galleries[this.activeGalleryIndex].images && this.galleries[this.activeGalleryIndex].images[this.activeImageIndex] ) { return this.galleries[this.activeGalleryIndex].images[this.activeImageIndex].url } else { // TOOD return 404 page - does this do it? throw({ statusCode: 404, message: 'Image Not Found' }) } } }, watch: { $route () { const query = this.$route.query if (!query || !query.gallery) { return } this.$nextTick(() => { const gallery = parseInt(query.gallery) const image = parseInt(query.image) || 0 if (gallery !== this.activeGalleryIndex) { this.activeRow = gallery this.activeGalleryIndex = gallery } if (image !== this.activeImageIndex) { this.activeImageIndex = image this.showImage = image } }) } }, created () { let query = this.$route.query this.activeGalleryIndex = query.gallery ? parseInt(query.gallery) : 0 this.activeRow = this.activeGalleryIndex this.activeImageIndex = query.image ? parseInt(query.image) : 0 }, mounted () { window.addEventListener('resize', () => { this.imageViewerIsVisible = false }) this.$nextTick(() => { this.isMounted = true }) }, methods: { handleFeaturedClick (index) { this.activeRow = index this.activeImageIndex = 0 this.activeGalleryIndex = index this.setQueryString() }, handleThumbClick(gallery, image) { this.activeGalleryIndex = gallery this.activeImageIndex = image this.imageViewerIsVisible = true this.setQueryString() }, handleClickNext () { this.activeImageIndex++; }, handleClickPrev () { this.activeImageIndex--; }, setQueryString () { this.$router.push({ path: this.$route.path, query: { gallery: this.activeGalleryIndex, image: this.activeImageIndex, }, }) } } } </script> <style lang="scss" scoped> .gallery-page { position: relative; height: 100%; width: 100%; } .image-viewer { position: absolute; width: 100%; height: 100%; top: 0; left: 0; } @media (max-width: $bp__layout) { .page-heading { z-index: 5; position: absolute; width: 100%; top: 0; left: 50%; transform: translateX(-50%); font-size: 2rem; pointer-events: none; } .gallery-page { padding-top: $site-menu__header-height; } .gallery { position: relative; height: 100%; width: 100%; overflow-x: hidden; overflow-y: auto; } .gallery__thumbs { z-index: 10; position: absolute; top: 0; left: 0; } .gallery__featured { width: 100vw; } .close-viewer { font-size: 10em; cursor: pointer; } } @media (min-width: $bp__layout) { .page-heading { position: absolute; font-size: 3.5rem; top: 0; left: 0; margin-top: 0; max-width: calc(100% - 3rem - #{$gallery-featured-width--compact}); @media (min-width: $bp__gallery-compact) { max-width: calc(100% - 2rem - #{$gallery-featured-width}); } } .mobile-only { display: none; } .gallery-page { padding-left: $site-menu__header-width; } .gallery { display: flex; flex-direction: row; justify-content: space-between; position: relative; height: 100%; width: 100%; overflow: hidden; } .gallery__featured { order: 2; flex: 0 0 $gallery-featured-width--compact; overflow-y: auto; @media (min-width: $bp__gallery-compact) { flex-basis: $gallery-featured-width; } } .gallery__thumbs { order: 1; display: flex; flex-direction: column; justify-content: space-between; padding-left: 8px; overflow: hidden; } .gallery__nav { display: none; } .close-viewer { display: none; } } .load-transition { transition: opacity 2s; opacity: 0; &--1 { transition-delay: 2s; } &--2 { transition-delay: 3s; } @at-root .is-mounted & { opacity: 1; } } </style>