alex-sharoff-website/components/gallery/Gallery.vue
2023-11-11 10:34:31 +04:00

169 lines
4.1 KiB
Vue

<template>
<section class="transition-opacity duration-500 ease-in-out opacity-0"
:class="[galleryLoading ? 'opacity-0' : 'opacity-100']">
<FilterGroup
:options="categories"
:initial-option="initialCategory"
@change="selectedCategory = $event"
v-if="filterEnabled"/>
<div id='gallery' class='columns-auto min-h-screen items-center mt-2 sm:mt-5'>
<GalleryItem
v-for='img in filteredPhotos'
:key='img.id'
:category='img.category'
:image='img.image'
:thumb-size='img.thumbSize'
/>
</div>
</section>
</template>
<script>
import lightGallery from 'lightgallery';
import lgThumbnail from 'lightgallery/plugins/thumbnail';
import lgZoom from 'lightgallery/plugins/zoom';
import lgFullScreen from 'lightgallery/plugins/fullscreen';
import ImagesLoaded from "imagesloaded/imagesloaded.js";
import {mapState} from "vuex";
import FilterGroup from "@/components/gallery/FilterGroup.vue";
import Shuffle from 'shufflejs'
// let ScrollReveal;
// if (process.browser) {
// ScrollReveal = require('scrollreveal/dist/scrollreveal')
// }
export default {
name: 'Gallery',
components: {FilterGroup},
props: {
initialCategory: {type: String},
images: {type: Array, default: []},
filterEnabled: {type: Boolean, default: false},
allCategoryEnabled: {type: Boolean, default: false},
},
created() {
this.ALL_CATEGORY = Shuffle.ALL_ITEMS;
// Object storage
this.shuffle = null
this.lg = null
},
data: function () {
return {
selectedCategory: this.initialCategory,
galleryLoading: true,
}
},
computed: {
...mapState(["categoriesNames"]),
categories() {
// Go through all images, collect unique categories keys
let categories = [...new Set(this.images.map((img) => img.category))]
if (this.allCategoryEnabled) {
categories = [this.ALL_CATEGORY, ...categories]
}
// Prepare data for GalleryFilter: category key & human-readable name
return categories.map(c => {
return {
value: c,
name: this.categoriesNames[c] ?? "UNKNOWN"
}
})
},
filteredPhotos() {
if (this.selectedCategory === this.ALL_CATEGORY || this.selectedCategory === null) {
return this.images;
} else {
return this.images.filter((photo) => photo.category === this.selectedCategory);
}
},
},
watch: {
filteredPhotos: function () {
this.$nextTick(() => {
this.refreshGallery()
})
},
},
methods: {
refreshGallery() {
// Update LightGallery elements (click ability etc)
this.lg.refresh()
// Filter Shuffle & prevent from breaking the layout
this.shuffle.resetItems()
// Jerky animation fix
setTimeout(() => {
this.shuffle.filter(this.selectedCategory);
}, 300);
},
galleryInit(element) {
this.lg = lightGallery(element, {
plugins: [lgThumbnail, lgZoom, lgFullScreen],
mode: "lg-fade", // animation mode for fullscreen images
selector: '.gallery-item',
swipeToClose: false,
speed: 400,
alignThumbnails: "left",
download: false,
fullScreen: true,
mobileSettings: {
controls: true,
showCloseIcon: true,
thumbnail: false,
closeOnTap: false,
fullScreen: true
}
});
},
shuffleInit(element) {
this.shuffle = new Shuffle(element, {
group: this.initialCategory,
itemSelector: '.gallery-item',
delimiter: ',',
speed: 500,
})
},
},
mounted() {
let $gallery = document.querySelector('#gallery')
this.galleryInit($gallery)
ImagesLoaded('#gallery', {background: true}, () => {
console.log("ImagesLoaded")
this.shuffleInit($gallery)
this.galleryLoading = false
});
}
};
</script>
<style lang='css'>
@import 'lightgallery/css/lightgallery.css';
@import 'lightgallery/css/lg-thumbnail.css';
@import 'lightgallery/css/lg-zoom.css';
@import 'lightgallery/css/lg-fullscreen.css';
</style>