/vue-easy-lightbox

A tiny lightbox component for Vue.js 3.0 :tada::tada: https://xiongamao.github.io/vue-easy-lightbox/

Primary LanguageTypeScriptMIT LicenseMIT

vue-easy-lightbox

A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch .

npm npm npm

English | 中文文档 | Homepage

Vue-easy-lightbox@1.x only supports Vue.js 3, if you need Vue.js 2 version please check here.

Installation

Package managers

$ npm install --save vue-easy-lightbox@next
# OR
$ yarn add vue-easy-lightbox@next

Direct Download

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>

Different Builds

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)

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). 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'

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:

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'
    }
  }
})

Usage

Using UMD in browser

<!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>

Register VueApp component

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

<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

<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

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:

<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

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

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

License

MIT