###### tags: `Web` `FrontEnd` `Vue` `Nuxt`
# Photoswipe使用Vue封裝(TypeScript)並建立畫廊(Gallery)顯示與撥放功能
**## 注意:本文使用Material UI套件為 [Vuetify](https://vuetifyjs.com/en/)**
## 一、安裝
### a.使用npm安裝 PhotoSwipe
`npm install photoswipe`
使用ts的,需再安裝
`npm install --save @types/photoswipe`
### b.安裝後新增VPhotoSwipe.vue檔案
## 二、新增VPhotoSwipe並封裝PhotoSwipe
### a. 新增HTML Template Code [根據官網使用說明直接複製Html Code](https://reurl.cc/NZ1xl5)
```=Html
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div ref="pswp" class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element, as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides. PhotoSwipe keeps only 3 slides in DOM to save memory. -->
<div class="pswp__container">
<!-- don't modify these 3 pswp__item elements, data is added later on -->
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
```
### b.新增Sytle部分,Import PhotoSwipe Package CSS file
```=CSS
@import 'photoswipe/dist/photoswipe.css';
@import 'photoswipe/dist/default-skin/default-skin.css';
```
### c.新增TypeScipt部分
#### Import
Import PhotoSwipe 與 PhotoSwipeUIDefault
```=TypeScript
import PhotoSwipe from 'PhotoSwipe';
import PhotoSwipeUIDefault from 'PhotoSwipe/dist/photoswipe-ui-default';
```
#### 使用Ref讀取Dom Content
Html部分將ref pswp置入
```=Html
<div ref="pswp" class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
```
宣告Dom Element
```=TypeScript
@Ref('pswp')
private readonly pswpElement!: any;
```
#### 宣告Image Items,給外部使用做傳遞
```=TypeScript
@Prop()
private items!: PhotoSwipe.Item[];
```
#### [設定options](https://photoswipe.com/documentation/options.html)
```=TypeScript
private options = {
history: false,
focus: false,
showAnimationDuration: 0,
hideAnimationDuration: 0
};
```
#### 新增OpenPhotoSwipe Function
```=TypeScript
public OpenPhotoSwipe(index: number): void {
const phtoswipe = new PhotoSwipe(
this.pswpElement,
PhotoSwipeUIDefault,
this.items,
this.options
);
phtoswipe.init();
phtoswipe.goTo(index);
}
```
## 三、新增Gallery.vue Component,並使用封裝的VPhotoSwipe
### a. 撰寫TypeScript
#### 新增 PhotoImage Model
```=TypeScript
export interface PhotoImage{
id:number;
src:string;
w:number;
h:number;
}
```
宣告imgae,給外部使用做傳遞
```=TypeScript
@Prop()
private images!: PhotoImage[];
```
Import 撰寫的 VPhotoSwipe
```=TypeScript
import VPhotoSwipe from '~/yourpath/VPhotoSwipe.vue';
```
宣告使用VPhotoSwipe OpenPhotoSwipe方法
```=TypeScript
@Ref('photo-swipe')
private readonly photoSwipe!: InstanceType<typeof VPhotoSwipe>;
OnOpenPhotoSwipe(index: number): void {
this.photoSwipe.OpenPhotoSwipe(index);
}
```
#### Html Code
```=Html
<div>
<v-photo-swipe ref="photo-swipe" :items="images"></v-photo-swipe>
<v-row no-gutters>
<v-col
v-for="item in images"
:key="item.id"
class="d-flex child-flex"
cols="6"
sm="4"
>
<v-card flat tile class="d-flex" @click="OnOpenPhotoSwipe(item.id)">
<v-img :src="item.src" aspect-ratio="1.5" class="grey lighten-2">
<template #placeholder>
<v-row class="fill-height ma-0" align="center" justify="center">
<v-progress-circular
indeterminate
color="grey lighten-5"
></v-progress-circular>
</v-row>
</template>
</v-img>
</v-card>
</v-col>
</v-row>
</div>
```
## 四、使用Gallery Component
### Import Gallery Component 與 Gallery 的 PhotoImage Model
```=TypeScript
import { PhotoImage } from '~/yourpath/Gallery.vue';
import Gallery from '@/yourpath/Gallery.vue';
@Component({
layout: 'home-stay',
components: {
Gallery,
},
})
```
### 宣告Images資料
```=TypeScript
private images : PhotoImage[] = [{
id:0,
src: 'https://websitedemos.net/home-stay-04/wp-content/uploads/sites/811/2021/04/gallery-01-free-img.jpg',
w: 1024,
h: 964,
},
{
id:1,
src: 'https://websitedemos.net/home-stay-04/wp-content/uploads/sites/811/2021/04/gallery-02-free-img.jpg',
w: 1024,
h: 964,
},
{
id:2,
src: 'https://websitedemos.net/home-stay-04/wp-content/uploads/sites/811/2021/04/gallery-03-free-img.jpg',
w: 1024,
h: 500,
},
{
id:3,
src: 'https://websitedemos.net/home-stay-04/wp-content/uploads/sites/811/2021/04/gallery-04-free-img.jpg',
w: 1024,
h: 964,
},
{
id:4,
src: 'https://websitedemos.net/home-stay-04/wp-content/uploads/sites/811/2021/04/gallery-05-free-img.jpg',
w: 1024,
h: 964,
},
{
id:5,
src: 'https://websitedemos.net/home-stay-04/wp-content/uploads/sites/811/2021/04/gallery-06-free-img.jpg',
w: 1024,
h: 500,
},
```
### Html使用
```=Html
<v-col cols="12">
<gallery :images="images"></gallery>
</v-col>
```
## 五、效果

