Lightbox для Vue

Повноекранний Lightbox-галерея зображень і відео для Vue 3 на основі @reelkit/vue-lightbox.

Подивитися демо наживо →

Features

Зображення та відео
Вбудована підтримка слайдів-відео
Дотикові жести
Свайп для гортання
Свайп для закриття
Свайп угору закриває
Навігація з клавіатури
Стрілки + Escape
Повний екран
Кросбраузерний API
Переходи
Зсув, затухання, переворот, наближення
Preloading
±2 сусідні слайди завантажуються заздалегідь
Перемикач звуку
Звук вмикається й вимикається для кожного слайда
Стани завантаження
Індикатор і власний слот
Обробка помилок
Значок помилки та власний слот
Слоти з областю видимості
6 налаштовних зон-слотів
v-model
Двостороння прив’язка v-model:is-open
Стан в URL
Посилання, якими можна ділитися й зберігати в закладки
Слайдшоу
Автоперехід за бажанням, із відтворенням і паузою
Завантаження
Кнопка за бажанням, що зберігає активний елемент

Встановлення

bash
npm install @reelkit/vue-lightbox @reelkit/vue lucide-vue-next

Не забудьте імпортувати стилі:

typescript
import '@reelkit/vue-lightbox/styles.css';
Icons

Стандартні елементи керування використовують lucide-vue-next for icons. If you prefer a different icon library, use the #controls та #navigation з областю видимості, щоб передати власні.

Швидкий старт

Імпортуйте таблицю стилів і компонент LightboxOverlay , а відкриттям і закриттям керуйте через v-model:is-open.

App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { LightboxOverlay, type LightboxItem } from '@reelkit/vue-lightbox';
import '@reelkit/vue-lightbox/styles.css';

const images: LightboxItem[] = [
  {
    src: '/cdn/samples/images/image-01.jpg',
    title: 'Mountain River',
    description: 'A beautiful mountain river',
  },
  {
    src: '/cdn/samples/images/image-02.jpg',
    title: 'Snowy Peaks',
  },
  {
    src: '/cdn/samples/images/image-03.jpg',
    title: 'Misty Forest',
    description: 'Morning fog over the forest canopy',
  },
  {
    src: '/cdn/samples/images/image-04.jpg',
    title: 'Autumn Trail',
  },
  {
    src: '/cdn/samples/images/image-05.jpg',
    title: 'Ocean Cliff',
    description: 'Dramatic cliffs above the Pacific',
  },
  {
    src: '/cdn/samples/images/image-06.jpg',
    title: 'Desert Dunes',
  },
];

const open = ref(false);
const startIndex = ref(0);

function openAt(i: number) {
  startIndex.value = i;
  open.value = true;
}
</script>

<template>
  <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px">
    <button
      v-for="(img, i) in images"
      :key="img.src"
      style="aspect-ratio:4/3;cursor:pointer"
      @click="openAt(i)"
    >
      <img :src="img.src" style="width:100%;height:100%;object-fit:cover" />
    </button>
  </div>

  <LightboxOverlay
    v-model:is-open="open"
    :items="images"
    :initial-index="startIndex"
  />
</template>

Слоти з областю видимості

Шість іменованих слотів з областю видимості дають повністю налаштувати поверхні оверлея. Не задавайте слот, щоб лишити вбудований типовий вигляд; залиште слот порожнім (наприклад, через v-if="false") to hide that section entirely.

SlotScopeОпис
#slideSlideSlotScopeЗамінює вміст окремого слайда (обов’язково для слайдів-відео)
#controlsControlsSlotScopeЗамінює верхню смугу керування (закриття, лічильник, повний екран)
#navigationNavigationSlotScopeЗамінює стрілки навігації вперед і назад
#infoInfoSlotScopeЗамінює нижній градієнтний оверлей із заголовком та описом
#loadingLoadingSlotScopeВласний індикатор завантаження
#errorErrorSlotScopeВласний індикатор помилки
vue
<template>
  <LightboxOverlay v-model:is-open="open" :items="items">
    <!-- Custom info overlay -->
    <template #info="{ item }">
      <div class="my-caption">
        <h2>{{ item.title }}</h2>
        <p>{{ item.description }}</p>
      </div>
    </template>

    <!-- Custom navigation -->
    <template #navigation="{ onPrev, onNext, activeIndex, count }">
      <div class="my-nav">
        <button :disabled="activeIndex === 0" @click="onPrev">Prev</button>
        <span>{{ activeIndex + 1 }} / {{ count }}</span>
        <button :disabled="activeIndex === count - 1" @click="onNext">Next</button>
      </div>
    </template>

    <!-- Custom controls -->
    <template #controls="{ onClose, isFullscreen, onToggleFullscreen }">
      <div class="my-controls">
        <button @click="onToggleFullscreen">
          {{ isFullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen' }}
        </button>
        <button @click="onClose">Close</button>
      </div>
    </template>
  </LightboxOverlay>
</template>

Підтримка відео

Слайди-відео вмикаються за бажанням, тож типовий бандл лишається без обв’язки для аудіо та відео. Викличте useVideoSlideRenderer(items) і передайте повернені VideoSlideRenderer / VideoControlsRenderer в слоти оверлея #slide та #controls . Загорніть оверлей у повернений SoundProvider щоб вбудований перемикач звуку мав контекст. Повернений об’єкт має тип UseVideoSlideRendererResult: SoundProvider, hasVideo, VideoSlideRenderer і VideoControlsRenderer.

vue
<script setup lang="ts">
import { ref } from 'vue';
import {
  LightboxOverlay,
  useVideoSlideRenderer,
  type LightboxItem,
} from '@reelkit/vue-lightbox';
import '@reelkit/vue-lightbox/styles.css';

const open = ref(false);
const items: LightboxItem[] = [
  { src: '/image-01.jpg', title: 'Image' },
  {
    type: 'video',
    src: '/clip.mp4',
    poster: '/clip.jpg',
    title: 'Clip',
  },
];

const { VideoSlideRenderer, VideoControlsRenderer, SoundProvider } =
  useVideoSlideRenderer(items);
</script>

<template>
  <SoundProvider>
    <LightboxOverlay v-model:is-open="open" :items="items">
      <template #slide="scope">
        <VideoSlideRenderer v-bind="scope" />
      </template>
      <template #controls="scope">
        <VideoControlsRenderer v-bind="scope" />
      </template>
    </LightboxOverlay>
  </SoundProvider>
</template>

Спільний елемент <video> що живить слайди-відео, працює за тим самим патерном, що й reel-плеєр для Vue: на iOS відтворення триває між змінами слайдів і не потребує окремого жесту користувача на кожному.

Повний екран

Використовуйте useFullscreen from @reelkit/vue щоб стежити за станом повного екрана для елемента за посиланням або перемикати його. Вбудована кнопка повного екрана в Lightbox працює через той самий композабл.

vue
<script setup lang="ts">
import { shallowRef } from 'vue';
import { useFullscreen } from '@reelkit/vue';

const containerRef = shallowRef<HTMLDivElement | null>(null);
const { isFullscreen, toggle } = useFullscreen({ elementRef: containerRef });
</script>

<template>
  <div ref="containerRef">
    <button @click="toggle">
      {{ isFullscreen.value ? 'Exit fullscreen' : 'Enter fullscreen' }}
    </button>
  </div>
</template>

Стан в URL

Подивитися демо наживо →

Build a controller with useOverlayUrlState from @reelkit/vue і передайте його в LightboxUrlOverlay as controller, and the address bar owns the gallery: it opens itself when the parameter names a slide and closes when the parameter goes away. Links are shareable, and the back button closes the gallery. It is a separate component from LightboxOverlay, so each carries exactly one open-state driver — the is-open модель або url controller, never both.

Вбудовані клавіші

Слайди можна адресувати вбудованим ключем — розгорніть urlIndexKey (за позицією) або urlStableIdKey (за стабільним id) into the controller — both re-exported from @reelkit/vue. See the посібник зі стану в URL та API ядра.

«Назад» закриває лише тоді, коли ви відкрили галерею всередині застосунку — посилання додало запис, тож «назад» повертає до галереї. За надісланим посиланням у новій вкладці історії позаду немає, тож кнопка «назад» виведе із сайту; кнопка закриття або Escape прибирає параметр на місці й лишає вас у галереї.

vue
<script setup lang="ts">
import { LightboxUrlOverlay, type LightboxItem } from '@reelkit/vue-lightbox';
import { useOverlayUrlState, urlIndexKey, urlStableIdKey } from '@reelkit/vue';
import '@reelkit/vue-lightbox/styles.css';

const props = defineProps<{ images: LightboxItem[] }>();

const photo = useOverlayUrlState({
  param: 'photo',
  ...urlIndexKey(() => props.images.length),
});
</script>

<template>
  <!-- Opening is a link — the href is the open action. No open flag, no
       handler: the overlay reads the URL and opens itself. -->
  <RouterLink v-for="(img, i) in props.images" :key="img.src" :to="`?photo=${i}`">
    <img :src="img.src" />
  </RouterLink>

  <LightboxUrlOverlay :controller="photo" :items="props.images" />
</template>

Композабл приймає один об’єкт опцій і повертає UrlStateController (with set, index, value). Keep it for programmatic control: set — низькорівневий запис, який оверлей робить усередині (зміна слайда та set(null) для закриття). Ним же можна керувати оверлеєм програмно: set(index) відкриває його — так само, як перехід за параметром. Але для відкриття краще звичайне посилання: href можна надіслати, відкрити в новій вкладці, а кнопка «назад» його закриє — і все це без жодного обробника.

Full useOverlayUrlState options (param, adapter, codec, locator): see the довіднику API для Vue.

LightboxUrlOverlay приймає лише :controller (обов’язково), @close emit, а також усі візуальні та поведінкові пропси, які передає далі LightboxOverlay forwards (items, transition-fn, the scoped slots, and so on) — but no is-open.

  • Відкриття коштує одного запису в історії; гортання слайдів замінює його, тож сто свайпів не додають жодного — один крок назад завжди виходить із галереї.
  • Надіслане посилання на кшталт ?photo=3 відкриває галерею на цьому слайді. Параметр, який не називає жодного слайда, прибирається з URL, а не наполягає на слайді, що не відкриється.

У застосунку з роутером передайте адаптер. Прямий запис в історію лишає власне місцеположення роутера застарілим, і наступна навігація втрачає параметр.

vue
<script setup lang="ts">
import { useVueRouterUrlAdapter } from '@reelkit/vue/vue-router-url-adapter';

const adapter = useVueRouterUrlAdapter();
const photo = useOverlayUrlState({
  param: 'photo',
  adapter,
  ...urlIndexKey(() => images.length),
});
</script>

<template>
  <LightboxUrlOverlay :controller="photo" :items="images" />
</template>

Стабільні посилання. Індекс адресує за позицією, тож закладка відкриє інше зображення, щойно список перевпорядкують. urlStableIdKey адресує за стабільним id, scanning the live list — one call covers the common case.

vue
<script setup lang="ts">
const photo = useOverlayUrlState({
  param: 'photo',
  ...urlStableIdKey({ items: () => images }),
});
</script>

<template>
  <LightboxUrlOverlay :controller="photo" :items="images" />
</template>

Pass hashCodec: base64UrlCodec щоб закодувати id в URL у base64url — оборотне маскування, а не криптографічний хеш.

Адресуєте за іншим полем ( slug), or page an infinite feed with locateAsync, and build the codec/locator самі: codec записує ідентичність в URL, locator знаходить, де воно тепер лежить.

vue
<script setup lang="ts">
const photo = useOverlayUrlState({
  param: 'photo',
  codec: { decode: (raw) => raw, encode: (id) => id },
  locator: {
    locate: (id) => images.findIndex((x) => x.slug === id),
    identify: (index) => images[index].slug,
  },
});
</script>

<template>
  <LightboxUrlOverlay :controller="photo" :items="images" />
</template>

Нескінченні та посторінкові галереї. locate синхронний, тож відповідає лише за вже завантажені елементи — надіслане посилання на зображення 400 у стрічці, де завантажено 20, нічого не знайде. locateAsync — запасний варіант, що викликається лише коли не знайшлося: завантажте потрібні сторінки й поверніть індекс, який ця ідентичність отримала.

Shortcut

Keying by the item’s id? Не пишіть кодек і локатор вручну — передайте locateAsync просто в urlStableIdKey({ items, locateAsync }) (він вантажить дані, якщо не знайшов, і повертає індекс). Розгорнутий варіант нижче — для адресації за іншим полем або для повного контролю.

vue
<script setup lang="ts">
const photo = useOverlayUrlState({
  param: 'photo',
  codec: { decode: (raw) => raw, encode: (id) => id },
  locator: {
    locate: (id) => items.value.findIndex((x) => x.id === id),
    identify: (index) => items.value[index].id,
    locateAsync: async (id) => {
      const loaded = await loadById(id); // or loadUntil(id) — fetch just that one, or page up to it
      if (!loaded) return null; // exhausted — link names no item
      items.value = loaded; // commit; the overlay renders from this
      return loaded.findIndex((x) => x.id === id); // wherever it landed
    },
  },
});
</script>

<template>
  <LightboxUrlOverlay :controller="photo" :items="items" />
</template>

Поки він у процесі, Lightbox лишається закритим, а параметр — недоторканим, тож пряме посилання переживає запит. null або відмова прибирає параметр. Відповідь, що приходить після зміни URL, після закриття або після демонтажу, відкидається, тож повільний запит не відкриє слайд, якого ніхто не просив. Те, що він повертає, є остаточним: це індекс щойно завантажених даних, і Lightbox бере його як є, не перечитуючи items, which Vue has not re-rendered yet.

Автоперехід

Задайте auto-advance, щоб галерея після відкриття гралася як слайдшоу. Типово вимкнено, тож наявний Lightbox рендериться й поводиться як раніше.

vue
<script setup lang="ts">
import { ref } from 'vue';
import { LightboxOverlay, type LightboxApi } from '@reelkit/vue-lightbox';

const open = ref(false);
const lightbox = ref<LightboxApi | null>(null);
</script>

<template>
  <LightboxOverlay
    ref="lightbox"
    v-model:is-open="open"
    :items="items"
    auto-advance
    :auto-advance-interval="4000"
  />
  <!-- The template ref drives it from outside: lightbox?.pause() -->
</template>
  • Зображення лишаються на екрані auto-advance-interval (типово 5000 мс), відлічуваних із моменту, коли зображення завантажилося, тож повільне зображення ніколи не пропускається, перш ніж його хтось побачив. Для зображення, що не завантажилося, відлік іде від помилки.
  • Відео програються один раз замість циклу й переходять далі, коли закінчуються. VideoSlideRenderer робить це за вас; власний #slide читає autoAdvance зі своєї області видимості й повідомляє про кінець через onEnded.
  • Воно чекає, поки миша лежить на елементі керування (кнопці, посиланні чи підписі), під час свайпу і поки сторінка прихована, а потім продовжує з місця зупинки.
  • Ручне перемикання (стрілки, клавіші, колесо, свайп) запускає інтервал нового слайда з нуля; слайдшоу лишається увімкненим.
  • На останньому слайді воно зупиняється, якщо не задано loop. Кнопка відтворення й паузи серед елементів керування показує стан і дає глядачеві його перемкнути; play() і pause() у LightboxApi роблять те саме з коду.

Власний слот #controls отримує isAutoAdvancing і, лише коли auto-advance увімкнено, onToggleAutoAdvance — рендерте PlayPauseButton, коли він є. Сам таймінг — це createSlideshowController з @reelkit/core; див. посібник з автовідтворення і API ядра.

Завантаження

Задайте show-download, щоб додати до елементів керування кнопку завантаження. Вона зберігає активний елемент за його downloadUrl, а якщо його немає — за src, під іменем downloadName, а якщо його немає — під останнім сегментом URL.

vue
<script setup lang="ts">
import { ref } from 'vue';
import {
  CloseButton,
  DownloadButton,
  LightboxOverlay,
  type LightboxItem,
} from '@reelkit/vue-lightbox';

const open = ref(false);
const items: LightboxItem[] = [
  {
    src: 'https://cdn.example.com/beach-1600.jpg',
    // Save the original rather than the resized preview
    downloadUrl: 'https://cdn.example.com/beach-original.jpg',
    downloadName: 'beach.jpg',
  },
];
</script>

<template>
  <LightboxOverlay v-model:is-open="open" :items="items" show-download>
    <!-- A custom bar shows the buttons only when their handler is there -->
    <template #controls="{ onClose, isDownloading, onDownload }">
      <DownloadButton
        v-if="onDownload"
        :is-downloading="isDownloading"
        :on-press="onDownload"
      />
      <CloseButton :on-press="onClose" />
    </template>
  </LightboxOverlay>
</template>

Файл завантажується через fetch і зберігається, бо браузер ігнорує атрибут download на посиланні на інше джерело й відкрив би файл замість збереження. Коли fetch не вдається — зазвичай це сервер на іншому джерелі, що не надсилає заголовків CORS, — файл відкривається в новій вкладці, де глядач усе ще може його зберегти. Віддавайте файли з Access-Control-Allow-Origin, щоб зберігати одним кліком. Поки триває завантаження, кнопка вимкнена.

Власний слот #controls отримує isDownloading і, лише коли show-download увімкнено, onDownload — рендерте DownloadButton, коли він є. Помічник — це downloadFile з @reelkit/core; див. посібник із завантаження.

Кнопки керування

КомпонентПропсиОпис
PlayPauseButtonPlayPauseButtonProps: isPlaying, onPress, className?Перемикач слайдшоу (іконка Play або Pause, aria-pressed під час відтворення). Стандартні елементи керування показують її з auto-advance.
DownloadButtonDownloadButtonProps: isDownloading, onPress, className?Кнопка завантаження, вимкнена, поки isDownloading. Стандартні елементи керування показують її з show-download.
CloseButtonCloseButtonProps: onPress, className?Стандартна кнопка закриття, яку рендерить панель керування; розмістіть її у власному слоті #controls, щоб зберегти вбудований вигляд.
CounterCounterProps: currentIndex, count, className?Стандартна плашка лічильника «3 / 10»; розмістіть її у власному слоті #controls, щоб зберегти вбудований вигляд.
FullscreenButtonFullscreenButtonProps: isFullscreen, onPress, className?Стандартний перемикач повного екрана; його іконка йде за isFullscreen.
SoundButtonSoundButtonProps: isMuted, onPress, className?Стандартний перемикач звуку для відео-елементів; його іконка йде за isMuted.

Частини слайда та навігації

КомпонентПропсиОпис
ImageSlideImageSlideProps: src, alt?, isActive, onReady?, onLoadError?Стандартний слайд-зображення, який рендерить оверлей; розмістіть його у власному слоті #slide, щоб зберегти вбудований вигляд для зображень.
LightboxVideoSlideLightboxVideoSlideProps: src, poster?, isActive, size, slideKey, loop?, onPlaying?, onWaiting?, onLoadError?Стандартний слайд-відео, що грає через спільний елемент <video>; useVideoSlideRenderer рендерить його за вас.
LightboxNavigationLightboxNavigationProps: activeIndex, count, loop?, onPrev, onNextСтандартні стрілки «назад» і «вперед»; розмістіть їх у власному слоті #navigation, щоб зберегти вбудований вигляд.

Довідник API

Пропси LightboxOverlay

LightboxOverlayProps

PropТипТипове значенняОпис
isOpenbooleanrequiredКерує видимістю; якщо false, оверлей прибирається з DOM. Прив’язується через v-model:is-open.
itemsLightboxItem[]requiredМасив елементів (зображення або відео)
initialIndexnumber0Індекс початково видимого елемента, від нуля
transitionFnTransitionTransformFnslideTransitionФункція переходу між слайдами. Імпортуйте вбудовану (slideTransition, flipTransition, lightboxFadeTransition, lightboxZoomTransition) або передайте власну. Якщо не задано, використовується slideTransition.
showInfobooleantrueЧи показувати інформаційний оверлей із заголовком та описом
showControlsbooleantrueЧи показувати верхню смугу керування (закриття, лічильник, повний екран)
showNavigationbooleantrueЧи показувати стрілки навігації вперед і назад (лише на десктопі)
transitionDurationnumber300Тривалість анімації слайда в мілісекундах
swipeDistanceFactornumber0.12Мінімальна частка відстані свайпу (0–1), щоб змінити слайд
swipeToCloseDirection'up' | 'down''up'Напрямок жесту свайпу для закриття на мобільних
loopbooleanfalseЧи переходить слайдер з останнього слайда на перший
enableNavKeysbooleantrueВмикає навігацію стрілками клавіатури
enableWheelbooleantrueВмикає навігацію колесом миші
wheelDebounceMsnumber200Тривалість дебаунсу подій колеса в мілісекундах
autoAdvancebooleanfalseГрати галерею як слайдшоу. Див. Автоперехід.
autoAdvanceIntervalnumber5000Скільки кожне зображення лишається на екрані під час слайдшоу, у мілісекундах, з моменту його завантаження
showDownloadbooleanfalseДодає кнопку завантаження для активного елемента. Див. Завантаження.
ariaLabelstring'Image gallery'Доступна назва області діалогу

Пропси LightboxUrlOverlay

LightboxUrlOverlayProps

Приймає всі візуальні та поведінкові пропси вище, крім is-open, and replaces it with a controller. Він видає close, slide-change та api-ready, but no update:is-open. initial-index тут ігнорується — слайд обирає position контролера, тож передане поруч значення перезаписувалося б на кожному відкритті.

PropТипТипове значенняОпис
controllerUrlStateControllerrequiredКонтролер із useOverlayUrlState. Його position вирішує, чи оверлей відкритий і який слайд показує; оверлей записує через нього назад на зміну слайда та на закриття.

Події LightboxOverlay

EventPayloadОпис
closevoidВидається, коли користувач закриває Lightbox
slide-changenumberВидається з новим індексом активного слайда після зміни
api-readyLightboxApiВидається, коли слайдер готовий, і відкриває імперативний API
update:is-openbooleanВидається на закриття; забезпечує роботу v-model:is-open

LightboxApi

Об'єкт, який видає api-ready; він же доступний через template ref компонента. Слайдер існує лише поки оверлей відкритий, тож кожен метод слайдера нічого не робить, поки він закритий; close() працює завжди.

МетодТипОпис
next()() => voidПереходить до наступного слайда з анімацією. Лишається на останньому слайді, якщо loop вимкнено.
prev()() => voidПовертається до попереднього слайда з анімацією. Лишається на першому слайді, якщо loop вимкнено.
goTo(index, animate?)(number, boolean?) => Promise<void>Переходить до слайда. index обмежується кількістю елементів, animate типово false. Завершується, коли рух закінчено.
adjust()() => voidПерераховує позицію слайда після зміни розкладки, якої оверлей сам не помітив
observe()() => voidЗнову починає слухати жести, клавіатуру та колесо миші після unobserve()
unobserve()() => voidПерестає слухати жести, клавіатуру та колесо миші; слайди лишаються на місці
close()() => voidЗакриває lightbox, як кнопка закриття або Escape
play()() => voidЗапускає слайдшоу, продовжуючи активний слайд з місця зупинки. Без auto-advance нічого не робить.
pause()() => voidЗупиняє слайдшоу; активний слайд зберігає свій прогрес. Без auto-advance нічого не робить.

Інтерфейс LightboxItem

FieldТипRequiredОпис
srcstringyesURL зображення або відео
type'image' | 'video'noТип елемента. Типово 'image'
posterstringnoМініатюра для елементів-відео
titlestringnoЗаголовок в інформаційному оверлеї
descriptionstringnoОпис під заголовком
widthnumbernoВласна ширина зображення в пікселях
heightnumbernoВласна висота зображення в пікселях
downloadUrlstringnoЩо зберігає кнопка завантаження. Типово — src
downloadNamestringnoІм’я файлу для збереження. Типово — останній сегмент шляху URL

Типи області видимості слотів

ТипFields
SlideSlotScope{ item, index, size: [number, number], isActive, autoAdvance, onReady, onWaiting, onError, onEnded }
ControlsSlotScope{ item, activeIndex, count, isFullscreen, isAutoAdvancing, isDownloading, onClose, onToggleFullscreen, onToggleAutoAdvance?, onDownload? }
NavigationSlotScope{ item, activeIndex, count, onPrev, onNext }
InfoSlotScope{ item, index }
LoadingSlotScope{ item, activeIndex }
ErrorSlotScope{ item, activeIndex }

Переходи

Передайте будь-яку TransitionTransformFn via the transition-fn Якщо імпортувати лише той перехід, який використовуєте, решту збирач прибере через tree-shaking. Типово — slideTransition , коли не задано.

FunctionОпис
slideTransitionТиповий. Горизонтальний зсув між слайдами; реекспортовано з @reelkit/vue.
lightboxFadeTransitionПлавне перетікання з легким горизонтальним зсувом. Власний для @reelkit/vue-lightbox.
flipTransition3D-переворот навколо осі Y; реекспортовано з @reelkit/vue.
lightboxZoomTransitionНовий слайд масштабується з 70% до 100% із затуханням. Власний для @reelkit/vue-lightbox.
vue
<script setup lang="ts">
import {
  LightboxOverlay,
  lightboxFadeTransition,
  lightboxZoomTransition,
} from '@reelkit/vue-lightbox';
</script>

<template>
  <!-- Built-in transition -->
  <LightboxOverlay
    v-model:is-open="open"
    :items="items"
    :transition-fn="lightboxFadeTransition"
  />

  <!-- Different built-in -->
  <LightboxOverlay
    v-model:is-open="open"
    :items="items"
    :transition-fn="lightboxZoomTransition"
  />
</template>

Завантаження вмісту та обробка помилок

Коли ви берете рендеринг на себе через слот #slide , в області слота доступні три колбеки життєвого циклу, щоб повідомляти стан завантаження. Lightbox стежить за станом кожного слайда й показує індикатор або значок помилки. Попереднє завантаження кешує зіпсовані URL, тож повторний перехід до невдалого слайда обходиться без нової спроби.

Колбеки життєвого циклу

КолбекТипОпис
onReady() => voidПовідомляє, що вміст слайда успішно завантажився (наприклад, зображення декодовано)
onWaiting() => voidПовідомляє, що вміст слайда вантажиться або буферизується (показує індикатор)
onError() => voidПовідомляє, що вміст слайда не завантажився (показує значок помилки)

Підключення колбеків у #slide

vue
<template>
  <LightboxOverlay v-model:is-open="open" :items="items">
    <template
      #slide="{ item, size, isActive, onReady, onWaiting, onError }"
    >
      <template v-if="item.type === 'video'">
        <video
          :src="item.src"
          :poster="item.poster"
          :autoplay="isActive"
          :style="{ width: `${size[0]}px`, height: `${size[1]}px`, objectFit: 'contain' }"
          @canplay="onReady"
          @waiting="onWaiting"
          @error="onError"
        />
      </template>
      <template v-else>
        <img
          :src="item.src"
          :style="{ width: `${size[0]}px`, height: `${size[1]}px`, objectFit: 'contain' }"
          @load="onReady"
          @error="onError"
        />
      </template>
    </template>
  </LightboxOverlay>
</template>

Власний слот завантаження

Скористайтеся пропсом #loading щоб замінити стандартний індикатор.

vue
<template>
  <LightboxOverlay v-model:is-open="open" :items="items">
    <template #loading="{ item, activeIndex }">
      <div class="my-loading">
        <span>Loading image {{ activeIndex + 1 }}…</span>
        <span class="muted">{{ item.title }}</span>
      </div>
    </template>
  </LightboxOverlay>
</template>

Власний слот помилки

Скористайтеся пропсом #error щоб замінити стандартний значок зіпсованого зображення.

vue
<template>
  <LightboxOverlay v-model:is-open="open" :items="items">
    <template #error="{ item, activeIndex }">
      <div class="my-error">
        <span>Failed to load</span>
        <span class="muted">{{ item.title ?? item.src }}</span>
      </div>
    </template>
  </LightboxOverlay>
</template>

Класи CSS

Усі класи CSS звичайні (не scoped), тож їх можна перекрити селекторами вищої специфічності в таблиці стилів, підключеній після @reelkit/vue-lightbox/styles.css. Для змін кольору, розміру та z-index краще беріть власні властивості CSS, описані в розділі Theming нижче.

ClassComponentОпис
.rk-lightbox-overlayOverlayКореневий контейнер (повноекранне тло)
.rk-lightbox-top-shadeOverlayВерхній градієнтний шар за елементами керування
.rk-lightbox-spinnerOverlayСтандартний індикатор завантаження
.rk-lightbox-errorOverlayКонтейнер стану помилки (зіпсоване зображення)
.rk-lightbox-error-textOverlayТекст стану помилки
.rk-lightbox-controls-leftControlsКонтейнер елементів керування вгорі ліворуч
.rk-lightbox-btnControlsКнопка керування (повний екран, звук тощо)
.rk-lightbox-play-pauseControlsКнопка відтворення й паузи слайдшоу (разом із .rk-lightbox-btn)
.rk-lightbox-downloadControlsКнопка завантаження (разом із .rk-lightbox-btn)
.rk-lightbox-closeControlsКнопка закриття
.rk-lightbox-counterControlsЗначок лічильника зображень
.rk-lightbox-navНавігаціяСтрілка навігації (і вперед, і назад)
.rk-lightbox-nav-prevНавігаціяСтрілка назад
.rk-lightbox-nav-nextНавігаціяСтрілка вперед
.rk-lightbox-infoInfoКонтейнер заголовка й опису
.rk-lightbox-info-titleInfoЗаголовок зображення
.rk-lightbox-info-descriptionInfoОпис зображення
.rk-lightbox-slideSlideКонтейнер слайда
.rk-lightbox-imgSlideЕлемент зображення
.rk-lightbox-video-containerVideoSlideКонтейнер слайда-відео (за бажанням)
.rk-lightbox-video-elementVideoSlideЕлемент відео (за бажанням)
.rk-lightbox-video-posterVideoSlideПостер відео (за бажанням)

Theming

Перевизначайте будь-яку власну властивість CSS --rk-lightbox-* на :root (або на будь-якому предку .rk-lightbox-overlay) to retheme. Direct declarations on .rk-lightbox-overlay перекрив би успадковані значення, тож тримайте перевизначення на селекторі предка.

TokenТипове значенняControls
--rk-lightbox-overlay-bg#000Колір фону
--rk-lightbox-overlay-z9999z-index оверлею
--rk-lightbox-top-shade-height80pxВисота верхнього затемнення
--rk-lightbox-top-shade-bglinear-gradient(rgba(0,0,0,0.6), transparent)Градієнт верхнього затемнення
--rk-lightbox-edge-padding16pxВідступ від краю для кнопок закриття, навігації та елементів керування
--rk-lightbox-btn-bgrgba(0, 0, 0, 0.5)Типовий фон кнопок закриття, навігації та малих кнопок
--rk-lightbox-btn-bg-hoverrgba(255, 255, 255, 0.2)Фон кнопок закриття, навігації та малих кнопок під час наведення
--rk-lightbox-btn-fg#fffКолір іконок кнопок закриття, навігації та малих кнопок
--rk-lightbox-btn-size36pxРозмір малої кнопки (перемикач повноекранного режиму тощо)
--rk-lightbox-btn-disabled-opacity0.5Непрозорість вимкненої малої кнопки (під час завантаження)
--rk-lightbox-close-size40pxРозмір кнопки закриття
--rk-lightbox-nav-size48pxРозмір стрілок «назад» і «далі»
--rk-lightbox-nav-opacity0.7Непрозорість стрілок «назад» і «далі» у спокої
--rk-lightbox-counter-bgrgba(0, 0, 0, 0.5)Фон плашки лічильника
--rk-lightbox-counter-fg#fffКолір тексту лічильника
--rk-lightbox-info-bglinear-gradient(transparent, rgba(0,0,0,0.8))Градієнт затемнення під підписом
--rk-lightbox-title-size18pxРозмір шрифту заголовка
--rk-lightbox-description-size14pxРозмір шрифту опису
--rk-lightbox-video-bg#000Фон смуг навколо <video>
css
<style>
:root {
  --rk-lightbox-overlay-bg: #0f172a;
  --rk-lightbox-btn-bg: rgba(99, 102, 241, 0.65);
  --rk-lightbox-btn-bg-hover: rgba(168, 85, 247, 0.85);
  --rk-lightbox-info-bg: linear-gradient(
    transparent,
    rgba(99, 102, 241, 0.55) 60%,
    rgba(168, 85, 247, 0.85)
  );
}
</style>

Accessibility

Корінь оверлея — модальний діалог (role="dialog", aria-modal="true"). Set the aria-label щоб змінити оголошення для екранного читача; типове значення — «Image gallery». Кожен слайд несе role="group", aria-roledescription="slide", and an aria-label виведений із позиції (наприклад, «Зображення 2 з 5»).

Lightbox захоплює фокус під час відкриття й повертає його на елемент-тригер після закриття. Tab і Shift+Tab циклічно проходять фокусовані елементи всередині; фокус, що вислизнув (клік поза Lightbox, програмна установка), повертається назад. Реалізовано через captureFocusForReturn та createFocusTrap from @reelkit/vue.

Клавіатурні скорочення

KeyAction
ArrowLeftПопереднє зображення
ArrowRightНаступне зображення
EscapeЗакрити Lightbox (або вийти з повноекранного режиму, якщо він активний)