vue-easy-lightbox
Version:
A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch
633 lines (555 loc) • 15.3 kB
Markdown
# vue-easy-lightbox
> A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch .
[](https://www.npmjs.com/package/vue-easy-lightbox)
[](https://www.npmjs.com/package/vue-easy-lightbox)
[](https://www.npmjs.com/package/vue-easy-lightbox)
English | [中文文档](https://github.com/XiongAmao/vue-easy-lightbox/blob/master/README-CN.md) | [Homepage](https://xiongamao.github.io/vue-easy-lightbox/)
> `Vue-easy-lightbox@1.x` only supports Vue.js 3, if you need Vue.js 2 version please check [here](https://github.com/XiongAmao/vue-easy-lightbox/tree/vue2.x).
## Installation
### Package managers
```shell
$ npm install --save vue-easy-lightbox@next
# OR
$ yarn add vue-easy-lightbox@next
```
### Direct Download
Include the CDN link in HTML.
```html
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-easy-lightbox@next/dist/vue-easy-lightbox.umd.min.js"></script>
<script>
const app = Vue.createApp({
// ... root component options
})
app.use(VueEasyLightbox) // global variable
app.mount('#app')
</script>
```
### Different Builds
Since `Vue 3.x` uses `ES2015` ([docs faq](https://vuejs.org/about/faq.html#what-browsers-does-vue-support)), there is no need to build `ES5` bundle, and `ES5` build is removed from version `1.6.0`.
<table>
<thead>
<tr>
<th>Module</th>
<th>Filename</th>
</tr>
</thead>
<tbody>
<tr>
<td>UMD(for browsers)</td>
<td>vue-easy-lightbox.umd.min.js</td>
</tr>
<tr>
<td>CommonJS</td>
<td>vue-easy-lightbox.common.min.js (pkg.main)</td>
</tr>
<tr>
<td>ES Module(for bundlers)</td>
<td>vue-easy-lightbox.esm.min.js (pkg.module)</td>
</tr>
</tbody>
</table>
### External CSS Build
> Added in: `v1.2.3`
By default, CSS is included in `dist/*.min.js`. In some special cases you may want to import CSS individually to avoid some problems ([CSP Violation](https://github.com/XiongAmao/vue-easy-lightbox/issues/75)). You can import builds without CSS and individual `.css` file from `dist/external-css/`.
```js
import VueEasyLightbox from 'vue-easy-lightbox/external-css'
// or
import VueEasyLightbox from 'vue-easy-lightbox/dist/external-css/vue-easy-lightbox.esm.min.js'
// you need to import css
import 'vue-easy-lightbox/external-css/vue-easy-lightbox.css'
// or
import 'vue-easy-lightbox/dist/external-css/vue-easy-lightbox.css'
```
#### TypeScript Checking error:
If your project is TypeScript project and you get this error message:
> `Could not find the declaration file for module 'vue-easy-lightbox/dist/external-css/vue-easy-lightbox.esm.min.js'`
Here are two ways to solve it.
Way 1: add `d.ts` in your project:
```ts
declare module 'vue-easy-lightbox/dist/external-css/vue-easy-lightbox.esm.min.js' {
import VueEasyLightbox from 'vue-easy-lightbox'
export * from 'vue-easy-lightbox'
export default VueEasyLightbox
}
```
Way 2: alias
If you're using webpack: [webpack alias docs](https://webpack.js.org/configuration/resolve/#resolvealias)
```js
// wepback.config.js
module.exports = {
//...
resolve: {
alias: {
'vue-easy-lightbox$': 'vue-easy-lightbox/dist/external-css/vue-easy-lightbox.esm.min.js',
},
},
};
// in your component
import VueEasyLightbox from 'vue-easy-lightbox' // work
```
Or vitejs: [vitejs alias](https://vitejs.dev/config/shared-options.html#resolve-alias)
```js
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
resolve: {
alias: {
'vue-easy-lightbox$': 'vue-easy-lightbox/dist/external-css/vue-easy-lightbox.esm.min.js'
}
}
})
```
## Usage
### Using `UMD` in browser
```html
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-easy-lightbox@next/dist/vue-easy-lightbox.umd.min.js"></script>
</head>
<body>
<div id="app">
<div class="">
<div v-for="(src, index) in imgs" :key="index" class="pic" @click="() => showImg(index)">
<img :src="src" />
</div>
</div>
<vue-easy-lightbox :visible="visibleRef" :imgs="imgs" :index="indexRef" @hide="onHide"></vue-easy-lightbox>
</div>
<script>
const { ref } = Vue
const app = Vue.createApp({
setup() {
const visibleRef = ref(false)
const indexRef = ref(0)
const imgs = [
'https://via.placeholder.com/450.png/',
'https://via.placeholder.com/300.png/',
'https://via.placeholder.com/150.png/',
{ src: 'https://via.placeholder.com/450.png/', title: 'this is title' }
]
const showImg = (index) => {
indexRef.value = index
visibleRef.value = true
}
const onHide = () => visibleRef.value = false
return {
visibleRef,
indexRef,
imgs,
showImg,
onHide
}
}
})
// Registering VueEasyLightbox for your VueApp.
app.use(VueEasyLightbox)
app.mount('#app')
</script>
</body>
</html>
```
### Register VueApp component
```javascript
import Vue from 'vue'
import VueEasyLightbox from 'vue-easy-lightbox'
const app = Vue.createApp({
// ... app options
})
app.use(VueEasyLightbox)
app.mount('#app')
```
### Basic Usage in SFC
```html
<template>
<div>
<button @click="showSingle">Show single picture.</button>
<button @click="showMultiple">Show a group of pictures.</button>
<vue-easy-lightbox
:visible="visibleRef"
:imgs="imgsRef"
:index="indexRef"
@hide="onHide"
></vue-easy-lightbox>
</div>
</template>
<script>
// If VueApp is already registered with VueEasyLightbox, there is no need to register it here.
import VueEasyLightbox from 'vue-easy-lightbox'
import { ref, defineComponent } from 'vue'
export default defineComponent({
components: {
VueEasyLightbox
},
setup() {
const visibleRef = ref(false)
const indexRef = ref(0) // default 0
const imgsRef = ref([])
// Img Url , string or Array of string
// ImgObj { src: '', title: '', alt: '' }
// 'src' is required
// allow mixing
const onShow = () => {
visibleRef.value = true
}
const showSingle = () => {
imgsRef.value = 'http://via.placeholder.com/350x150'
// or
// imgsRef.value = {
// title: 'this is a placeholder',
// src: 'http://via.placeholder.com/350x150'
// }
onShow()
}
const showMultiple = () => {
imgsRef.value = [
'http://via.placeholder.com/350x150',
'http://via.placeholder.com/350x150'
]
// or
// imgsRef.value = [
// { title: 'test img', src: 'http://via.placeholder.com/350x150' },
// 'http://via.placeholder.com/350x150'
// ]
indexRef.value = 0 // index of imgList
onShow()
}
const onHide = () => (visibleRef.value = false)
return {
visibleRef,
indexRef,
imgsRef,
showSingle,
showMultiple,
onHide
}
}
})
</script>
```
### Use vue slot custom buttons or toolbar
```html
<vue-easy-lightbox ...>
<template v-slot:prev-btn="{ prev }">
<button @click="prev">show the prev</button>
</template>
<template v-slot:next-btn="{ next }">
<button @click="next">show the next</button>
</template>
<template v-slot:close-btn="{ close }">
<button @click="close">close lightbox</button>
</template>
<template v-slot:toolbar="{ toolbarMethods }">
<button @click="toolbarMethods.zoomIn">zoom in</button>
<button @click="toolbarMethods.zoomOut">zoom out</button>
<button @click="toolbarMethods.rotateLeft">Anticlockwise rotation</button>
<button @click="toolbarMethods.rotateRight">clockwise rotation</button>
</template>
</vue-easy-lightbox>
```
Reference: [Slots](https://vuejs.org/guide/components/slots.html)
### Composables
> Added in `v1.7.0`
`useEasyLightbox` provides some simple methods and states to help you use `setup()`.
It is optional. You can customize your state.
Usage:
```html
<template>
<div>
<button @click="show">show</button>
<vue-easy-lightbox
:visible="visibleRef"
:imgs="imgsRef"
:index="indexRef"
@hide="onHide"
/>
</div>
</template>
<script>
import { defineComponent } from 'vue'
import VueEasyLightbox, { useEasyLightbox } from 'vue-easy-lightbox'
export default defineComponent({
components: {
VueEasyLightbox
},
setup() {
const {
// methods
show, onHide, changeIndex,
// refs
visibleRef, indexRef, imgsRef
} = useEasyLightbox({
// src / src[]
imgs: [
'http://via.placeholder.com/250x150',
'http://via.placeholder.com/300x150',
'http://via.placeholder.com/350x150'
],
// initial index
initIndex: 0
})
return {
visibleRef,
indexRef,
imgsRef,
show,
onHide
}
}
})
</script>
```
#### Type declaration
```ts
export interface Img {
src?: string
title?: string
alt?: string
}
export interface UseEasyLightboxOptions {
/**
* image src/Img or list of images src/Img
* @default ''
*/
imgs: Img | string | (Img | string)[];
/**
* initial index of imgList
* @default 0
*/
initIndex?: number;
}
export declare const useEasyLightbox: (options: UseEasyLightboxOptions) => {
imgsRef: Ref<Img | string | (Img | string)[]>;
indexRef: Ref<number | undefined>;
visibleRef: Ref<boolean>;
show: (index?: Ref<number> | number | Event) => void;
onHide: () => void;
changeIndex: (index?: number) => void;
};
```
## Options
Props
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>visible</td>
<td>Boolean</td>
<td>required</td>
<td>Control lightbox display</td>
</tr>
<tr>
<td>imgs</td>
<td>String/String[]/ImgObject:{ src: string, title?: string, alt?: string }/ImgObject[]</td>
<td>required</td>
<td>Image's src / array of src / ImgObject:{ src, title?, alt? } / array of ImgObject / array of ImgObject.</td>
</tr>
<tr>
<td>index</td>
<td>Number</td>
<td>0</td>
<td>Index of imgList</td>
</tr>
<tr>
<td>loop</td>
<td>Boolean</td>
<td>false</td>
<td>Pass true to enable continuous loop mode.</td>
</tr>
<tr>
<td>scrollDisabled (scroll-disabled)</td>
<td>Boolean</td>
<td>true</td>
<td>Pass true to disable scrolling when modal is visible.</td>
</tr>
<tr>
<td>escDisabled (esc-disabled)</td>
<td>Boolean</td>
<td>false</td>
<td>By default, press the esc key to close Modal during presentation.</td>
</tr>
<tr>
<td>moveDisabled (move-disabled)</td>
<td>Boolean</td>
<td>false</td>
<td>Pass true to disable image movement and enable swipe.</td>
</tr>
<tr>
<td>rotateDisabled (rotate-disabled)</td>
<td>Boolean</td>
<td>false</td>
<td>Pass true to disable image rotation.</td>
</tr>
<tr>
<td>zoomDisabled (zoom-disabled)</td>
<td>Boolean</td>
<td>false</td>
<td>Pass true to disable image zooming.</td>
</tr>
<tr>
<td>pinchDisabled (pinch-disabled)</td>
<td>Boolean</td>
<td>false</td>
<td>Pass true to disable pinching.</td>
</tr>
<tr>
<td>maskClosable (mask-closable)</td>
<td>Boolean</td>
<td>true</td>
<td>Enable or disable click mask to close vue-easy-lightbox.</td>
</tr>
<tr>
<td>dblclickDisabled (dblclick-closable)</td>
<td>Boolean</td>
<td>false</td>
<td>Enable or disable double-click on img to zoom in/out.</td>
</tr>
<tr>
<td>teleport</td>
<td>string | Element</td>
<td>-</td>
<td>Specify the mount node for vue-easy-lightbox.</td>
</tr>
<tr>
<td>swipeTolerance (swipe-tolerance)</td>
<td>Number</td>
<td>50</td>
<td>Specify the number of pixel you have to swipe.</td>
</tr>
<tr>
<td>zoomScale</td>
<td>Number</td>
<td>0.12</td>
<td>Specify the step between zoom levels.</td>
</tr>
<tr>
<td>maxZoom</td>
<td>Number</td>
<td>3</td>
<td>Specify the maximum level of zoom scale.</td>
</tr>
<tr>
<td>minZoom</td>
<td>Number</td>
<td>0.1</td>
<td>Specify the minimum level of zoom scale.</td>
</tr>
<tr>
<td>rtl</td>
<td>Boolean</td>
<td>false</td>
<td>support RTL (right to left) languages</td>
</tr>
</tbody>
</table>
Event
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Return Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>hide</td>
<td>When you click modal mask or close Btn, component will emit this event</td>
<td>-</td>
</tr>
<tr>
<td>on-error</td>
<td>Image loading error</td>
<td>event (event.target is not the image to be displayed)</td>
</tr>
<tr>
<td>on-prev / <br> on-prev-click</td>
<td>Emit when prev btn is clicked or when the user swiped right</td>
<td>(oldIndex, newIndex)</td>
</tr>
<tr>
<td>on-next / <br> on-next-click</td>
<td>Emit when next btn is clicked or when the user swiped left</td>
<td>(oldIndex, newIndex)</td>
</tr>
<tr>
<td>on-index-change</td>
<td>Emit when imgs's index is changed</td>
<td>(oldIndex, newIndex)</td>
</tr>
<tr>
<td>on-rotate</td>
<td>Emit when image rotate</td>
<td>deg: number (clockwise angle deg)</td>
</tr>
</tbody>
</table>
Slot & Scoped Slot
<table>
<thead>
<tr>
<th>Slot Name</th>
<th>Slot Props</th>
<th>Slot Props Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>prev-btn</td>
<td>prev</td>
<td>Function</td>
<td>Show the prev img</td>
</tr>
<tr>
<td>next-btn</td>
<td>next</td>
<td>Function</td>
<td>Show the next img</td>
</tr>
<tr>
<td>close-btn</td>
<td>close</td>
<td>Function</td>
<td>Close modal</td>
</tr>
<tr>
<td>toolbar</td>
<td>
toolbarMethods: {
zoomIn,
zoomOut,
rotate(rotateLeft),
rotateLeft,
rotateRight
}
</td>
<td>{ Function }</td>
<td>Zoom in, zoom out, rotate(rotateLeft), rotateLeft, rotateRight</td>
</tr>
<tr>
<td>loading</td>
<td>-</td>
<td>-</td>
<td>Loading icon</td>
</tr>
<tr>
<td>onerror</td>
<td>-</td>
<td>-</td>
<td>Error Placeholder</td>
</tr>
</tbody>
</table>
## License
[MIT](http://opensource.org/licenses/MIT)