Behaviour
- The page will show 4 images (out of 6 images)
- When click on image to launch the image viewer, the navbar/gallery will show all 6 images.
v-viewer/Viewer.js doesn't support dynamic image loading via API methods, thus we need to manipulate the img DOM by loading extra images as hidden img.
The reason I don't preload the extra images as hidden img is to avoid browser loading the hidden images (unless user click to view image).
Solution 1: using v-viewer
<template> <div> <div class="viewer" v-viewer="viewerOptions"> <img v-for="image in visibleImages" :src="image.src" :key="image.src" :data-href="image.href" :alt="image.alt"> <img v-for="image in hiddenImages" :src="image.src" :key="image.src" :data-href="image.href" :alt="image.alt" style="display: none;"> </div> </div></template><script>export default { data() { return { renderHiddenMore: false, viewerOptions: { movable: false, rotatable: false, scalable: false, url: 'data-href', title(image, imageData) { // if want to show blank title, must use alt=" " return image.alt }, show: () => { if (!this.renderHiddenMore) { console.log('load more') this.renderHiddenMore = true // delay hack to get the new viewer object is being generated setTimeout(() => { console.log('launch viewer') const viewer = this.$el.querySelector('.viewer').$viewer viewer.show() }, 500); } } }, images: [ { src: 'https://picsum.photos/id/1/150/150', href: 'https://picsum.photos/id/1/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/2/150/150', href: 'https://picsum.photos/id/2/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/3/150/150', href: 'https://picsum.photos/id/3/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/4/150/150', href: 'https://picsum.photos/id/4/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/15/150/150', href: 'https://picsum.photos/id/15/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/16/150/150', href: 'https://picsum.photos/id/16/800/800', alt: ' ' } ] } }, computed: { visibleImages() { return this.images.slice(0, 4) }, hiddenImages() { return this.renderHiddenMore ? this.images.slice(4) : [] } }}</script>
Disadvantage
- Slightly slower because
v-viewer
is initially loaded with 4 images, then itercepted usingshow
event to be reinitialized with additional images before being shown - The delay hack to get the new viewer object might be unreliable
Solution 2: using Viewer.js directly
<template> <div> <div class="viewer"> <img v-for="(image, index) in visibleImages" :src="image.src" :key="image.src" :data-href="image.href" :alt="image.alt" @click="showImage(index)"> <img v-for="image in hiddenImages" :src="image.src" :key="image.src" :data-href="image.href" :alt="image.alt" style="display: none;"> </div> </div></template><script>import Viewer from 'viewerjs'export default { data() { return { renderHiddenMore: false, viewerOptions: { movable: false, rotatable: false, scalable: false, url: 'data-href', title(image, imageData) { // if want to show blank title, must use alt=" " return image.alt }, $viewer: null }, images: [ { src: 'https://picsum.photos/id/1/150/150', href: 'https://picsum.photos/id/1/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/2/150/150', href: 'https://picsum.photos/id/2/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/3/150/150', href: 'https://picsum.photos/id/3/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/4/150/150', href: 'https://picsum.photos/id/4/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/15/150/150', href: 'https://picsum.photos/id/15/800/800', alt: ' ' }, { src: 'https://picsum.photos/id/16/150/150', href: 'https://picsum.photos/id/16/800/800', alt: ' ' } ] } }, computed: { visibleImages() { return this.images.slice(0, 4) }, hiddenImages() { return this.renderHiddenMore ? this.images.slice(4) : [] } }, methods: { showImage(index) { if (!this.renderHiddenMore) { this.renderHiddenMore = true this.$nextTick(() => { console.log('create viewer') this.$viewer = new Viewer(this.$el.querySelector('.viewer'), this.viewerOptions) // this.$viewer.show() this.$viewer.view(index) }) } else { this.$viewer.view(index) } } },}</script>