marc-leopold/components/GalleryPage.vue

286 lines
6.3 KiB
Vue
Raw Normal View History

2019-01-03 21:11:23 +00:00
<template>
2019-02-02 13:53:19 +00:00
<div class="gallery-page"
:class="{'is-mounted': isMounted }"
>
<GalleryImageViewer class="image-viewer"
2019-01-29 13:02:11 +00:00
ref="imageViewer"
:is-visible="imageViewerIsVisible"
2019-01-09 21:23:03 +00:00
:image-url="viewingImageUrl"
2019-01-10 13:28:35 +00:00
:has-next="activeImageIndex < galleries[activeGalleryIndex].images.length - 1"
:has-prev="activeImageIndex > 0"
@clickPrev="handleClickPrev"
@clickNext="handleClickNext"
@close="imageViewerIsVisible = false" />
2019-01-27 21:36:28 +00:00
<article class="gallery">
2019-02-17 15:21:32 +00:00
<h1 class="page-heading page-title"><span class="shadow-deco">{{ title }}</span></h1>
2019-02-02 13:53:19 +00:00
<GalleryFeatured class="gallery__featured load-transition load-transition--1"
:galleries="galleries"
:gallery-active="activeGalleryIndex"
@clicked="handleFeaturedClick" />
2019-02-02 13:53:19 +00:00
<GalleryThumbs class="gallery__thumbs load-transition load-transition--2"
2019-01-04 13:55:30 +00:00
:featured-height="featuredImageHeight"
:galleries="galleries"
2019-01-09 21:23:03 +00:00
:active-row="activeRow"
:active-index="activeImageIndex"
:show-image="showImage"
2019-01-09 21:23:03 +00:00
@thumbClick="handleThumbClick"/>
2019-01-27 21:36:28 +00:00
</article>
2019-01-03 21:11:23 +00:00
</div>
</template>
<script>
import GalleryFeatured from '@/components/GalleryFeatured'
import GalleryThumbs from '@/components/GalleryThumbs'
import GalleryImageViewer from '@/components/GalleryImageViewer'
2019-01-03 21:11:23 +00:00
export default {
components: {
GalleryFeatured,
GalleryThumbs,
2019-01-04 15:23:13 +00:00
GalleryImageViewer,
},
2019-01-03 21:11:23 +00:00
props: {
galleries: {
type: Array,
required: true
2019-02-17 15:21:32 +00:00
},
title: {
type: String,
required: false,
default () {
return 'My Galleries'
},
2019-01-03 21:11:23 +00:00
}
},
data () {
return {
2019-02-02 13:53:19 +00:00
isMounted: false,
2019-01-04 13:55:30 +00:00
featuredImageHeight: '16rem',
imageViewerIsVisible: false,
2019-01-09 21:23:03 +00:00
activeRow: 0,
activeGalleryIndex: 0,
activeImageIndex: 0,
showImage: 0,
2019-01-09 21:23:03 +00:00
}
},
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' })
}
2019-01-03 21:11:23 +00:00
}
},
2019-01-28 12:37:04 +00:00
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
2019-01-28 12:37:04 +00:00
if (gallery !== this.activeGalleryIndex) {
this.activeRow = gallery
this.activeGalleryIndex = gallery
}
if (image !== this.activeImageIndex) {
this.activeImageIndex = image
this.showImage = image
}
})
2019-01-28 12:37:04 +00:00
}
},
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 })
2019-02-02 13:53:19 +00:00
this.$nextTick(() => {
this.isMounted = true
})
},
2019-01-03 21:11:23 +00:00
methods: {
handleFeaturedClick (index) {
this.activeRow = index
2019-01-28 09:57:48 +00:00
this.activeImageIndex = 0
this.activeGalleryIndex = index
2019-01-28 09:57:48 +00:00
this.setQueryString()
2019-01-09 21:23:03 +00:00
},
handleThumbClick(gallery, image) {
this.activeGalleryIndex = gallery
this.activeImageIndex = image
2019-01-10 13:28:35 +00:00
this.imageViewerIsVisible = true
2019-01-28 09:57:48 +00:00
this.setQueryString()
2019-01-10 13:28:35 +00:00
},
handleClickNext () {
this.activeImageIndex++;
},
handleClickPrev () {
this.activeImageIndex--;
2019-01-28 09:57:48 +00:00
},
setQueryString () {
this.$router.push({
path: this.$route.path,
query: {
gallery: this.activeGalleryIndex,
image: this.activeImageIndex,
},
})
}
2019-01-03 21:11:23 +00:00
}
}
</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;
}
2019-01-03 21:11:23 +00:00
@media (max-width: $bp__layout) {
2019-01-27 21:36:28 +00:00
.page-heading {
z-index: 5;
position: absolute;
width: 100%;
top: 0;
left: 50%;
transform: translateX(-50%);
font-size: 2rem;
pointer-events: none;
}
2019-01-03 21:11:23 +00:00
.gallery-page {
padding-top: $site-menu__header-height;
}
2019-01-04 13:55:30 +00:00
.gallery {
2019-01-03 21:11:23 +00:00
position: relative;
height: 100%;
2019-01-04 09:24:38 +00:00
width: 100%;
2019-01-03 21:11:23 +00:00
overflow-x: hidden;
overflow-y: auto;
}
2019-01-04 13:55:30 +00:00
.gallery__thumbs {
2019-01-27 21:36:28 +00:00
z-index: 10;
2019-01-04 13:55:30 +00:00
position: absolute;
top: 0;
left: 0;
}
2019-01-04 16:18:45 +00:00
.gallery__featured {
width: 100vw;
}
.close-viewer {
font-size: 10em;
cursor: pointer;
}
}
2019-01-03 21:11:23 +00:00
@media (min-width: $bp__layout) {
2019-01-27 21:36:28 +00:00
.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;
}
2019-01-04 09:24:38 +00:00
2019-01-03 21:11:23 +00:00
.gallery-page {
padding-left: $site-menu__header-width;
}
2019-01-04 13:55:30 +00:00
.gallery {
2019-01-04 09:56:46 +00:00
display: flex;
flex-direction: row;
2019-01-04 09:56:46 +00:00
justify-content: space-between;
2019-01-04 09:24:38 +00:00
position: relative;
height: 100%;
width: 100%;
overflow: hidden;
}
2019-01-04 13:55:30 +00:00
.gallery__featured {
order: 2;
2019-01-17 11:42:41 +00:00
flex: 0 0 $gallery-featured-width--compact;
2019-01-04 13:55:30 +00:00
overflow-y: auto;
2019-01-17 11:42:41 +00:00
@media (min-width: $bp__gallery-compact) {
flex-basis: $gallery-featured-width;
}
2019-01-04 13:55:30 +00:00
}
.gallery__thumbs {
order: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
2019-01-12 20:08:07 +00:00
padding-left: 8px;
2019-01-04 13:55:30 +00:00
overflow: hidden;
}
2019-01-04 15:23:13 +00:00
.gallery__nav {
display: none;
}
.close-viewer {
display: none;
}
2019-01-03 21:11:23 +00:00
}
2019-02-02 13:53:19 +00:00
.load-transition {
transition: opacity 2s;
opacity: 0;
&--1 {
transition-delay: 2s;
}
&--2 {
transition-delay: 3s;
}
@at-root .is-mounted & {
opacity: 1;
}
}
2019-01-03 21:11:23 +00:00
</style>