Skip to content

События

События можно подписывать двумя способами: через опцию on при инициализации или через метод on().

Список событий

Единая концепция: каждое событие — одно явление, без дубликатов (например, только created, только resized).

Жизненный цикл

  • created — после создания и инициализации
  • beforeDestroy — перед уничтожением
  • destroyed — при уничтожении
  • refresh — вызван update() (пересчёт размеров/позиций)
  • optionsUpdated — обновлены опции через updateOptions()

Смена слайда

  • beforeSlideChange — перед сменой слайда
  • slideChangeStart — начало смены (старт анимации)
  • slideChangeEnd — смена завершена
  • beforeTransitionStart — перед началом анимации перехода (для loop)
  • transitionStart — начало анимации перехода
  • transitionEnd — конец анимации перехода
  • scroll — во время прокрутки (тики анимации / драг)
  • progress — прогресс прокрутки 0..1 (только при !loop)
  • reachBeginning — достигнут первый слайд
  • reachEnd — достигнут последний слайд

Взаимодействие

  • click — клик по слайду
  • dragStart — начало перетаскивания
  • drag — во время перетаскивания
  • dragEnd — конец перетаскивания

Состояние и обновления

  • resized — завершилось изменение размера контейнера
  • breakpoint — смена breakpoint
  • lock — слайдер заблокирован
  • unlock — слайдер разблокирован
  • disabled — слайдер отключён (вызван disable())
  • enabled — слайдер включён (вызван enable())

Видимость слайдов

  • visible — слайд вошёл в видимую область
  • hidden — слайд вышел из видимой области

Видимость слайдера (viewport)

  • sliderVisible — слайдер вошёл в viewport (модуль visibility)
  • sliderHidden — слайдер вышел из viewport

Автопрокрутка (модуль autoplay)

Бескрутящаяся лента (модуль marquee)

Видео (модуль video)

  • videoReady — видео готово к воспроизведению
  • videoPlay — видео начало воспроизведение
  • videoPause — видео на паузе
  • videoEnded — видео завершило воспроизведение
  • videoProgress — прогресс воспроизведения видео 0..1

Ленивая загрузка

  • lazyLoaded — изображение успешно загружено
  • lazyLoadError — ошибка загрузки изображения

Модули навигации

Внутренние / для расширений

  • setTranslate — перед применением transform к контейнеру (для эффектов)
  • beforeLoopFix — перед коррекцией loop
  • loopFix — после коррекции loop

Подписка на события

Через опцию on

javascript
const slider = new Tvist('.slider', {
  on: {
    slideChangeStart: (index) => {
      console.log('Слайд изменился:', index)
    },
    resized: () => {
      console.log('Размер изменился')
    }
  }
})

Через метод on()

javascript
slider.on('slideChangeStart', (index) => {
  console.log('Слайд изменился:', index)
})

slider.on('resized', () => {
  console.log('Размер изменился')
})

Отписка от событий

javascript
const handler = (index) => console.log(index)

// Подписка
slider.on('slideChangeStart', handler)

// Отписка от конкретного обработчика
slider.off('slideChangeStart', handler)

// Отписка от всех обработчиков события
slider.off('slideChangeStart')

Подписка на одно срабатывание

javascript
slider.once('slideChangeStart', (index) => {
  console.log('Выполнится только один раз:', index)
})

Lifecycle события

События жизненного цикла слайдера.

created

typescript
created: (tvist: Tvist) => void

Вызывается после создания и инициализации слайдера. К этому моменту на root уже добавлен класс Tvist.CLASSES.created (например, tvist-v1--created). См. Классы состояний на root.

Параметры:

  • tvist - экземпляр слайдера

Примеры:

javascript
const slider = new Tvist('.slider', {
  on: {
    created: (tvist) => {
      console.log('Слайдер создан')
      console.log('Количество слайдов:', tvist.slides.length)
      
      // Инициализация дополнительной логики
      initCustomFeatures(tvist)
    }
  }
})

beforeDestroy

typescript
beforeDestroy: (tvist: Tvist) => void

Вызывается перед уничтожением (до очистки модулей и DOM). Класс Tvist.CLASSES.destroyed на root добавляется сразу после этого события.

destroyed

typescript
destroyed: (tvist: Tvist) => void

Вызывается при уничтожении слайдера. На root к этому моменту уже висит класс Tvist.CLASSES.destroyed (tvist-v1--destroyed). См. Классы состояний на root.

Параметры:

  • tvist — экземпляр слайдера

Примеры:

javascript
slider.on('beforeDestroy', (tvist) => {
  // Сохранить состояние перед очисткой
  saveState(tvist)
})

slider.on('destroyed', (tvist) => {
  console.log('Слайдер уничтожен')
  cleanupCustomFeatures(tvist)
})

optionsUpdated

typescript
optionsUpdated: (tvist: Tvist, newOptions: Partial<TvistOptions>) => void

Вызывается после динамического обновления опций через updateOptions().

Параметры:

  • tvist - экземпляр слайдера
  • newOptions - объект с обновлёнными опциями

Примеры:

javascript
slider.on('optionsUpdated', (tvist, newOptions) => {
  console.log('Обновлены опции:', newOptions)
  
  if (newOptions.perPage) {
    console.log('Изменено количество слайдов на:', newOptions.perPage)
  }
  
  if (newOptions.direction) {
    console.log('Изменено направление на:', newOptions.direction)
  }
})

События навигации

События, связанные с переключением слайдов.

beforeSlideChange

typescript
beforeSlideChange: (index: number) => void

Вызывается перед началом смены слайда (до начала анимации).

Параметры:

  • index - индекс целевого слайда

Примеры:

javascript
slider.on('beforeSlideChange', (index) => {
  console.log('Начинается переход к слайду:', index)
  
  // Можно отменить действия или подготовить UI
  showLoadingIndicator()
})

slideChangeStart

typescript
slideChangeStart: (index: number) => void

Вызывается при начале смены слайда (начало анимации).

Параметры:

  • index - индекс нового активного слайда

Примеры:

javascript
slider.on('slideChangeStart', (index) => {
  console.log(`Переход к слайду ${index + 1}`)
  
  // Обновление UI
  document.querySelector('.current-slide').textContent = index + 1
  
  // Обновление URL
  history.pushState(null, '', `#slide-${index}`)
})

slideChangeEnd

typescript
slideChangeEnd: (index: number) => void

Вызывается после завершения смены слайда (конец анимации).

Параметры:

  • index - индекс нового активного слайда

Примеры:

javascript
slider.on('slideChangeEnd', (index) => {
  console.log('Завершён переход к слайду:', index)
  
  // Ленивая загрузка для следующего слайда
  const nextSlide = slider.slides[index + 1]
  if (nextSlide) {
    lazyLoadImages(nextSlide)
  }
  
  hideLoadingIndicator()
})

События взаимодействия

click

typescript
click: (index: number, slide: HTMLElement, event: MouseEvent) => void

Клик по слайду (делегирование с контейнера). Аргументы: индекс слайда, элемент слайда, объект события.

dragStart

typescript
dragStart: () => void

Вызывается при начале перетаскивания (mousedown или touchstart).

Примеры:

javascript
slider.on('dragStart', () => {
  console.log('Начато перетаскивание')
  
  // Приостановить автопрокрутку
  slider.root.classList.add('is-dragging')
  
  // Отключить другие взаимодействия
  disableOtherInteractions()
})

drag

typescript
drag: () => void

Вызывается во время перетаскивания (mousemove или touchmove).

Примеры:

javascript
slider.on('drag', () => {
  // Обновление индикаторов
  updateDragIndicator()
  
  // Отслеживание аналитики
  trackDragDistance()
})

dragEnd

typescript
dragEnd: () => void

Вызывается при завершении перетаскивания (mouseup или touchend).

Примеры:

javascript
slider.on('dragEnd', () => {
  console.log('Завершено перетаскивание')
  
  slider.root.classList.remove('is-dragging')
  
  // Возобновить другие взаимодействия
  enableOtherInteractions()
})

События обновления

События, связанные с изменением состояния слайдера.

scroll

typescript
scroll: () => void

Вызывается во время прокрутки (тики анимации или при драге). Для прогресса 0..1 используйте событие progress.

Примеры:

javascript
slider.on('scroll', () => {
  // Обновление parallax эффекта
  updateParallax()
  
  // Обновление прогресс-бара
  const progress = Math.abs(slider.engine.location.get())
  updateProgressBar(progress)
})

resized

typescript
resized: () => void

Вызывается после завершения изменения размера контейнера (throttle).

Примеры:

javascript
slider.on('resized', () => {
  console.log('Размер контейнера изменился')
  
  const width = slider.root.offsetWidth
  if (width < 768) {
    slider.updateOptions({ perPage: 1 })
  } else {
    slider.updateOptions({ perPage: 3 })
  }
})

refresh

typescript
refresh: () => void

Вызывается при вызове update() — пересчитаны размеры и позиции.

beforeTransitionStart

typescript
beforeTransitionStart: (data: { index: number; direction: 'next' | 'prev' }) => void

Вызывается перед началом анимации перехода. Используется внутренне для loop (коррекция индекса). Полезно для синхронизации с другими слайдерами или кастомной логики по направлению.

transitionStart / transitionEnd

typescript
transitionStart: (index: number) => void
transitionEnd: (index: number) => void

Начало и конец анимации перехода к слайду. При мгновенном переходе (instant: true) не вызываются.

progress

typescript
progress: (progress: number) => void

Прогресс прокрутки от 0 до 1. Вызывается только при loop: false (в loop нет однозначного прогресса).

reachBeginning / reachEnd

typescript
reachBeginning: () => void
reachEnd: () => void

Вызываются при достижении первого или последнего слайда (после slideChangeEnd).

breakpoint

typescript
breakpoint: (breakpoint: number | null) => void

Вызывается при смене breakpoint (активация адаптивных настроек).

Параметры:

  • breakpoint - значение активного breakpoint в пикселях, или null для базовых настроек

Примеры:

javascript
slider.on('breakpoint', (breakpoint) => {
  if (breakpoint === null) {
    console.log('Активны базовые настройки')
  } else {
    console.log(`Активен breakpoint: ${breakpoint}px`)
  }
  
  // Обновление UI в зависимости от breakpoint
  updateUIForBreakpoint(breakpoint)
})

lock

typescript
lock: () => void

Вызывается при блокировке слайдера (когда весь контент помещается в контейнер и прокрутка не нужна). На root при этом уже висит класс Tvist.CLASSES.locked (например, tvist-v1--locked). Подробнее см. Свойства → root, классы состояний.

Примеры:

javascript
slider.on('lock', () => {
  console.log('Слайдер заблокирован')
  
  // Скрыть навигационные элементы
  document.querySelector('.slider-nav').style.display = 'none'
  
  // Класс tvist-v1--locked уже добавлен на root; при необходимости можно добавить свой
  slider.root.classList.add('my-locked-state')
})

unlock

typescript
unlock: () => void

Вызывается при разблокировке слайдера. Класс Tvist.CLASSES.locked с root при этом снимается автоматически.

Примеры:

javascript
slider.on('unlock', () => {
  console.log('Слайдер разблокирован')
  
  // Показать навигационные элементы
  document.querySelector('.slider-nav').style.display = ''
  
  // Убрать свой класс (tvist-v1--locked снимается библиотекой)
  slider.root.classList.remove('my-locked-state')
})

disabled

typescript
disabled: (tvist: Tvist) => void

Вызывается при отключении слайдера через disable() (добавляется класс, блокируются события).

Параметры:

  • tvist — экземпляр слайдера

enabled

typescript
enabled: (tvist: Tvist) => void

Вызывается при включении слайдера через enable() после вызова disable().

Параметры:

  • tvist — экземпляр слайдера

visible / hidden

typescript
visible: (slide: HTMLElement, index: number) => void
hidden: (slide: HTMLElement, index: number) => void

Слайд вошёл в видимую область или вышел из неё (по viewport контейнера). Эмитит модуль slide-states.

sliderVisible / sliderHidden

typescript
sliderVisible: () => void
sliderHidden: () => void

Слайдер целиком вошёл в viewport страницы или вышел из него. Эмитит модуль visibility (при опции visibility: true). Используется для паузы/возобновления autoplay и marquee при уходе слайдера из зоны видимости.

Примеры:

javascript
slider.on('sliderVisible', () => {
  console.log('Слайдер виден на экране')
  // Можно возобновить фоновые процессы
})

slider.on('sliderHidden', () => {
  console.log('Слайдер скрыт (вкладка или прокрутка)')
  // Автопрокрутка и marquee приостанавливаются модулем автоматически
})

События Autoplay модуля

События модуля автопрокрутки (при опции autoplay: true или объекте настроек).

autoplayStart

typescript
autoplayStart: () => void

Вызывается при запуске автопрокрутки (вызов getModule('autoplay').getAutoplay().start() или старт по опциям).

autoplayStop

typescript
autoplayStop: () => void

Вызывается при полной остановке автопрокрутки.

autoplayPause

typescript
autoplayPause: () => void

Вызывается при постановке автопрокрутки на паузу (например, при наведении, если pauseOnHover: true).

autoplayResume

typescript
autoplayResume: () => void

Вызывается при возобновлении автопрокрутки после паузы.

autoplayProgress

typescript
autoplayProgress: (data: { progress: number; index: number }) => void

Прогресс до следующего перехода: progress от 0 до 1, index — текущий активный слайд. Вызывается во время ожидания перед сменой слайда (и при ожидании окончания видео, если waitForVideo: true).

Примеры:

javascript
slider.on('autoplayProgress', ({ progress, index }) => {
  document.querySelector('.progress-bar').style.width = `${progress * 100}%`
})

События Marquee модуля

События бескрутящейся ленты (при опции marquee: true или объекте настроек).

marqueeStart

typescript
marqueeStart: () => void

Вызывается при запуске marquee.

marqueeStop

typescript
marqueeStop: () => void

Вызывается при остановке marquee.

marqueePause

typescript
marqueePause: () => void

Вызывается при постановке marquee на паузу (например, при выходе слайдера из viewport).

marqueeResume

typescript
marqueeResume: () => void

Вызывается при возобновлении marquee.

События Video модуля

События модуля видео (при опции video: true или объекте настроек). Полезны для синхронизации с внешним UI или аналитикой.

videoReady

typescript
videoReady: (data: VideoEvent) => void

Вызывается, когда видео готово к воспроизведению (событие canplay). VideoEvent: { slide, video, index }.

videoPlay

typescript
videoPlay: (data: VideoEvent) => void

Вызывается при начале воспроизведения видео.

videoPause

typescript
videoPause: (data: VideoEvent) => void

Вызывается при постановке видео на паузу.

videoEnded

typescript
videoEnded: (data: VideoEvent) => void

Вызывается при окончании воспроизведения видео.

videoProgress

typescript
videoProgress: (data: VideoProgressEvent) => void

Прогресс воспроизведения: VideoProgressEvent содержит slide, video, index, progress (0..1), currentTime, duration.

Примеры:

javascript
slider.on('videoPlay', ({ video, index }) => {
  console.log('Воспроизведение слайда', index)
})

slider.on('videoProgress', ({ progress, currentTime, duration }) => {
  document.querySelector('.video-progress').style.width = `${progress * 100}%`
})

События навигации и модулей

Вызывается после монтирования стрелок навигации (модуль navigation). Без параметров.

pagination:mounted

Вызывается после монтирования пагинации (модуль pagination). Без параметров.

typescript
'navigation:click': (index: number) => void

Вызывается при клике по миниатюре в режиме thumbs (модуль thumbs). Передаётся индекс слайда, к которому выполняется переход.

Примеры:

javascript
slider.on('navigation:click', (index) => {
  console.log('Выбрана миниатюра:', index)
})

События для расширений

setTranslate

typescript
setTranslate: (tvist: Tvist, position: number) => void

Вызывается в Engine перед применением transform к контейнеру слайдов. Позиция в пикселях. Используется модулем эффектов (fade, cube и т.д.) для кастомной отрисовки. Подписываться только если нужно изменить способ применения трансформа (например, кастомный эффект).

beforeLoopFix

Вызывается в LoopModule перед выполнением коррекции индекса/позиции в режиме loop. Используется внутренне модулями (pagination, drag). Обычно не нужен в пользовательском коде.

loopFix

Вызывается в LoopModule после выполнения коррекции loop. Модули (pagination, drag) подписываются для обновления состояния. Обычно не нужен в пользовательском коде.

События LazyLoad модуля

События модуля ленивой загрузки изображений (требуется опция lazy: true).

lazyLoaded

typescript
lazyLoaded: (img: HTMLImageElement, slideIndex: number) => void

Вызывается когда изображение успешно загружено.

Параметры:

  • img (HTMLImageElement) - загруженное изображение
  • slideIndex (number) - индекс слайда, в котором находится изображение

Примеры:

javascript
const slider = new Tvist('.slider', {
  lazy: true,
  on: {
    lazyLoaded: (img, slideIndex) => {
      console.log(`Изображение загружено в слайде ${slideIndex}`)
      
      // Добавить класс для анимации появления
      img.classList.add('loaded')
      
      // Отслеживание в аналитике
      analytics.track('Image Loaded', {
        src: img.src,
        slideIndex: slideIndex,
        loadTime: performance.now()
      })
      
      // Показать уведомление
      showNotification(`Слайд ${slideIndex + 1} готов к просмотру`)
    }
  }
})

Пример с анимацией:

javascript
slider.on('lazyLoaded', (img, slideIndex) => {
  // Плавное появление изображения
  img.style.opacity = '0'
  img.style.transition = 'opacity 0.3s ease'
  
  setTimeout(() => {
    img.style.opacity = '1'
  }, 10)
})

Пример со счётчиком:

javascript
let loadedCount = 0
const totalImages = document.querySelectorAll('img[data-src]').length

slider.on('lazyLoaded', (img, slideIndex) => {
  loadedCount++
  
  const progress = (loadedCount / totalImages) * 100
  document.querySelector('.load-progress').textContent = 
    `Загружено: ${loadedCount} из ${totalImages} (${progress.toFixed(0)}%)`
  
  if (loadedCount === totalImages) {
    console.log('✅ Все изображения загружены!')
    hideLoader()
  }
})

lazyLoadError

typescript
lazyLoadError: (img: HTMLImageElement, slideIndex: number) => void

Вызывается при ошибке загрузки изображения (404, network error и т.д.).

Параметры:

  • img (HTMLImageElement) - изображение, которое не удалось загрузить
  • slideIndex (number) - индекс слайда, в котором находится изображение

Примеры:

javascript
const slider = new Tvist('.slider', {
  lazy: true,
  on: {
    lazyLoadError: (img, slideIndex) => {
      console.error(`Ошибка загрузки в слайде ${slideIndex}`)
      
      // Установить изображение-заглушку
      img.src = '/images/placeholder.jpg'
      img.alt = 'Изображение недоступно'
      
      // Добавить класс ошибки
      img.classList.add('load-error')
      
      // Логирование в систему мониторинга
      errorLogger.log({
        type: 'lazy_load_error',
        slide: slideIndex,
        src: img.dataset.src,
        timestamp: Date.now()
      })
    }
  }
})

Пример с повторной попыткой:

javascript
const MAX_RETRIES = 3
const retryCount = new WeakMap()

slider.on('lazyLoadError', (img, slideIndex) => {
  const attempts = retryCount.get(img) || 0
  
  if (attempts < MAX_RETRIES) {
    retryCount.set(img, attempts + 1)
    
    console.log(`Попытка ${attempts + 1} из ${MAX_RETRIES}`)
    
    // Повторная попытка через 2 секунды
    setTimeout(() => {
      const originalSrc = img.dataset.src
      if (originalSrc) {
        img.src = originalSrc + `?retry=${attempts + 1}`
      }
    }, 2000)
  } else {
    // После всех попыток показать placeholder
    img.src = '/images/error-placeholder.jpg'
    showErrorMessage(`Не удалось загрузить изображение в слайде ${slideIndex + 1}`)
  }
})

Пример с альтернативными источниками:

javascript
slider.on('lazyLoadError', (img, slideIndex) => {
  // Попробовать альтернативные CDN
  const fallbackCDNs = [
    'https://cdn1.example.com',
    'https://cdn2.example.com',
    'https://cdn3.example.com'
  ]
  
  const originalSrc = img.dataset.src
  const currentCDN = img.dataset.currentCdn || 0
  
  if (currentCDN < fallbackCDNs.length) {
    const newSrc = originalSrc.replace(/^https?:\/\/[^\/]+/, fallbackCDNs[currentCDN])
    img.dataset.currentCdn = currentCDN + 1
    img.src = newSrc
    
    console.log(`Пробуем CDN ${currentCDN + 1}: ${newSrc}`)
  } else {
    // Все CDN не работают
    img.src = '/images/placeholder.jpg'
    notifyAdmin(`Image load failed for slide ${slideIndex}`, originalSrc)
  }
})

Комбинированный пример:

javascript
const imageStats = {
  loaded: 0,
  errors: 0,
  total: 0
}

slider.on('created', () => {
  imageStats.total = document.querySelectorAll('img[data-src]').length
})

slider.on('lazyLoaded', (img, slideIndex) => {
  imageStats.loaded++
  updateLoadStats()
  
  // Добавить fade-in эффект
  img.style.animation = 'fadeIn 0.3s ease'
})

slider.on('lazyLoadError', (img, slideIndex) => {
  imageStats.errors++
  updateLoadStats()
  
  // Показать placeholder
  img.src = '/images/placeholder.jpg'
  img.classList.add('error')
  
  // Уведомление пользователю
  if (imageStats.errors > 3) {
    showNotification('Проблемы с загрузкой изображений. Проверьте подключение к интернету.')
  }
})

function updateLoadStats() {
  const total = imageStats.total
  const loaded = imageStats.loaded
  const errors = imageStats.errors
  const pending = total - loaded - errors
  
  console.log(`📊 Статистика: загружено ${loaded}, ошибок ${errors}, ожидает ${pending}`)
  
  document.querySelector('.stats').innerHTML = `
    <div>✅ Загружено: ${loaded}</div>
    <div>❌ Ошибки: ${errors}</div>
    <div>⏳ Ожидает: ${pending}</div>
  `
}

Примеры использования

Ленивая загрузка изображений (с модулем LazyLoad)

javascript
// Используйте встроенный модуль LazyLoad
const slider = new Tvist('.slider', {
  lazy: {
    preloadPrevNext: 1 // Предзагрузка соседних слайдов
  },
  on: {
    lazyLoaded: (img, slideIndex) => {
      console.log(`Изображение загружено в слайде ${slideIndex}`)
      
      // Плавное появление
      img.style.opacity = '0'
      setTimeout(() => {
        img.style.opacity = '1'
      }, 10)
    },
    lazyLoadError: (img, slideIndex) => {
      // Замена на placeholder при ошибке
      img.src = '/images/placeholder.jpg'
      console.error(`Ошибка загрузки в слайде ${slideIndex}`)
    }
  }
})

// Публичное API для ручной загрузки
const lazyModule = slider.modules.get('lazyload')

// Загрузить все оставшиеся изображения
lazyModule.loadAll()

// Загрузить конкретный слайд
lazyModule.loadSlide(5)

HTML разметка:

html
<div class="tvist-v1__slide">
  <img 
    data-src="image.jpg" 
    data-srcset="image-400.jpg 400w, image-800.jpg 800w"
    alt="Описание"
  >
</div>

Отслеживание просмотров в аналитике

javascript
slider.on('slideChangeEnd', (index) => {
  // Google Analytics
  gtag('event', 'slide_view', {
    slide_index: index,
    slide_id: slider.slides[index].dataset.id
  })
  
  // Или любая другая аналитика
  analytics.track('Slide Viewed', {
    index: index,
    realIndex: slider.realIndex,
    timestamp: Date.now()
  })
})

Синхронизация с другими элементами

javascript
const thumbnails = document.querySelectorAll('.thumbnail')

slider.on('slideChangeStart', (index) => {
  // Обновить активную миниатюру
  thumbnails.forEach((thumb, i) => {
    thumb.classList.toggle('active', i === index)
  })
  
  // Обновить текстовое описание
  const description = document.querySelector('.slide-description')
  description.textContent = slider.slides[index].dataset.description
})

Управление видео

javascript
slider.on('slideChangeStart', (index) => {
  // Остановить видео на предыдущих слайдах
  slider.slides.forEach((slide, i) => {
    if (i !== index) {
      const video = slide.querySelector('video')
      if (video) {
        video.pause()
        video.currentTime = 0
      }
    }
  })
  
  // Воспроизвести видео на текущем слайде
  const currentVideo = slider.slides[index].querySelector('video')
  if (currentVideo) {
    currentVideo.play()
  }
})

Прогресс-бар

javascript
function updateProgress() {
  const total = slider.slides.length
  const current = slider.activeIndex
  const progress = ((current + 1) / total) * 100
  
  document.querySelector('.progress-bar').style.width = `${progress}%`
  document.querySelector('.progress-text').textContent = 
    `${current + 1} / ${total}`
}

slider.on('slideChangeStart', updateProgress)
slider.on('created', updateProgress)

Кастомная анимация элементов

javascript
slider.on('slideChangeStart', (index) => {
  const currentSlide = slider.slides[index]
  
  // Анимация заголовка
  const title = currentSlide.querySelector('.slide-title')
  if (title) {
    title.style.animation = 'none'
    setTimeout(() => {
      title.style.animation = 'fadeInUp 0.6s ease'
    }, 10)
  }
  
  // Анимация описания с задержкой
  const description = currentSlide.querySelector('.slide-description')
  if (description) {
    description.style.animation = 'none'
    setTimeout(() => {
      description.style.animation = 'fadeInUp 0.6s ease 0.2s'
    }, 10)
  }
})

Автопауза при выходе из viewport

javascript
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (!entry.isIntersecting) {
      const autoplay = slider.getModule('autoplay')
      autoplay?.pause()
    } else {
      const autoplay = slider.getModule('autoplay')
      autoplay?.start()
    }
  })
})

slider.on('created', () => {
  observer.observe(slider.root)
})

slider.on('destroyed', () => {
  observer.disconnect()
})