A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch .
English | δΈζζζ‘£ | Homepage
[email protected]
only supports Vue.js 3, if you need Vue.js 2 version please check here.
$ npm install --save vue-easy-lightbox@next
# OR
$ yarn add vue-easy-lightbox@next
Include the CDN link in 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>
Since Vue 3.x
uses ES2015
(docs faq), there is no need to build ES5
bundle, and ES5
build is removed from version 1.6.0
.
Module | Filename |
---|---|
UMD(for browsers) | vue-easy-lightbox.umd.min.js |
CommonJS | vue-easy-lightbox.common.min.js (pkg.main) |
ES Module(for bundlers) | vue-easy-lightbox.esm.min.js (pkg.module) |
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). You can import builds without CSS and individual .css
file from dist/external-css/
.
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'
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:
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
// 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
// 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'
}
}
})
<!DOCTYPE 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>
import Vue from 'vue'
import VueEasyLightbox from 'vue-easy-lightbox'
const app = Vue.createApp({
// ... app options
})
app.use(VueEasyLightbox)
app.mount('#app')
<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>
<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
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:
<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>
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;
};
Props
Name | Type | Default | Description |
---|---|---|---|
visible | Boolean | required | Control lightbox display |
imgs | String/String[]/ImgObject:{ src: string, title?: string, alt?: string }/ImgObject[] | required | Image's src / array of src / ImgObject:{ src, title?, alt? } / array of ImgObject / array of ImgObject. |
index | Number | 0 | Index of imgList |
loop | Boolean | false | Pass true to enable continuous loop mode. |
scrollDisabled (scroll-disabled) | Boolean | true | Pass true to disable scrolling when modal is visible. |
escDisabled (esc-disabled) | Boolean | false | By default, press the esc key to close Modal during presentation. |
moveDisabled (move-disabled) | Boolean | false | Pass true to disable image movement and enable swipe. |
rotateDisabled (rotate-disabled) | Boolean | false | Pass true to disable image rotation. |
zoomDisabled (zoom-disabled) | Boolean | false | Pass true to disable image zooming. |
pinchDisabled (pinch-disabled) | Boolean | false | Pass true to disable pinching. |
maskClosable (mask-closable) | Boolean | true | Enable or disable click mask to close vue-easy-lightbox. |
dblclickDisabled (dblclick-closable) | Boolean | false | Enable or disable double-click on img to zoom in/out. |
teleport | string | Element | - | Specify the mount node for vue-easy-lightbox. |
swipeTolerance (swipe-tolerance) | Number | 50 | Specify the number of pixel you have to swipe. |
zoomScale | Number | 0.12 | Specify the step between zoom levels. |
maxZoom | Number | 3 | Specify the maximum level of zoom scale. |
minZoom | Number | 0.1 | Specify the minimum level of zoom scale. |
rtl | Boolean | false | support RTL (right to left) languages |
Event
Name | Description | Return Value |
---|---|---|
hide | When you click modal mask or close Btn, component will emit this event | - |
on-error | Image loading error | event (event.target is not the image to be displayed) |
on-prev / on-prev-click |
Emit when prev btn is clicked or when the user swiped right | (oldIndex, newIndex) |
on-next / on-next-click |
Emit when next btn is clicked or when the user swiped left | (oldIndex, newIndex) |
on-index-change | Emit when imgs's index is changed | (oldIndex, newIndex) |
on-rotate | Emit when image rotate | deg: number (clockwise angle deg) |
Slot & Scoped Slot
Slot Name | Slot Props | Slot Props Type | Description |
---|---|---|---|
prev-btn | prev | Function | Show the prev img |
next-btn | next | Function | Show the next img |
close-btn | close | Function | Close modal |
toolbar | toolbarMethods: { zoomIn, zoomOut, rotate(rotateLeft), rotateLeft, rotateRight } | { Function } | Zoom in, zoom out, rotate(rotateLeft), rotateLeft, rotateRight |
loading | - | - | Loading icon |
onerror | - | - | Error Placeholder |