Gogs 2a38f23eb6 -- 3 هفته پیش
..
README.md 2a38f23eb6 -- 3 هفته پیش
index.coffee 80710f8924 -- 3 هفته پیش
index.pug 46fa0734c5 -- 3 هفته پیش
index.styl 64342b1095 -- 3 هفته پیش

README.md

Компонент ImageSlider - Полная документация

Назначение компонента

ImageSlider - универсальный компонент для создания слайдеров изображений с поддержкой автоматической прокрутки, ручного управления, индикаторов и адаптивного дизайна. Компонент оптимизирован для работы с мультиязычным контентом и поддерживает различные типы медиа-контента.

git репозитарий

https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/ImageSlider/

Импорт и регистрация

# В основном файле приложения (app/temp.coffee)
components:
    'imageslider': require 'app/shared/ImageSlider'

Базовое использование

1. Простой слайдер с изображениями

imageslider(:slides="slides")

2. Слайдер с кастомными настройками

imageslider(
    :slides="featuredSlides"
    :autoplay="true"
    :interval="5000"
    :show-indicators="true"
    :show-controls="true"
)

Полный список props

slides (обязательный)

  • Тип: Array
  • Описание: Массив объектов слайдов
  • Структура слайда:

    {
    _id: String
    type: 'slide'
    title: Array[String]        # Мультиязычные заголовки
    content: Array[String]      # Мультиязычный контент
    image: Array[String]        # Мультиязычные пути к изображениям
    slide_data: {
      order: Number
      active: Boolean
      button_text: Array[String]
      button_link: Array[String]
      button_style: String
      text_color: Array[String]
      text_position: Array[String]
      overlay: Array[Boolean]
      overlay_opacity: Array[Number]
    }
    }
    

autoplay (опциональный)

  • Тип: Boolean
  • По умолчанию: true
  • Описание: Автоматическая прокрутка слайдов

interval (опциональный)

  • Тип: Number
  • По умолчанию: 4000
  • Описание: Интервал автоматической прокрутки в миллисекундах

showIndicators (опциональный)

  • Тип: Boolean
  • По умолчанию: true
  • Описание: Показывать индикаторы слайдов

showControls (опциональный)

  • Тип: Boolean
  • По умолчанию: true
  • Описание: Показывать кнопки управления (вперед/назад)

height (опциональный)

  • Тип: String
  • По умолчанию: '400px'
  • Описание: Высота слайдера (CSS значение)

transition (опциональный)

  • Тип: String
  • По умолчанию: 'slide'
  • Допустимые значения: 'slide', 'fade'
  • Описание: Тип анимации перехода между слайдами

События (Events)

@slide-change

  • Описание: Событие смены слайда
  • Payload: { currentSlide: Object, index: Number }
  • Пример:

    imageslider(:slides="slides" @slide-change="onSlideChange")
    

@slide-click

  • Описание: Событие клика по слайду
  • Payload: { slide: Object, index: Number }
  • Пример:

    imageslider(:slides="slides" @slide-click="onSlideClick")
    

Слоты (Slots)

[slide] (кастомный контент слайда)

  • Описание: Слот для кастомного отображения слайда
  • Props: { slide: Object, index: Number, active: Boolean }
  • Пример:

    imageslider(:slides="slides")
      template([slide]="{ slide, index, active }")
          div(class="relative h-full flex items-center justify-center")
              img(:src="slide.image" :alt="slide.title" class="w-full h-full object-cover")
              div(v-if="active" class="absolute inset-0 bg-black bg-opacity-40 flex items-center justify-center")
                  h2(class="text-white text-4xl font-bold") {{ slide.title }}
    

[indicators] (кастомные индикаторы)

  • Описание: Слот для кастомных индикаторов
  • Props: { slides: Array, currentIndex: Number, goToSlide: Function }
  • Пример:

    imageslider(:slides="slides")
      template([indicators]="{ slides, currentIndex, goToSlide }")
          div(class="flex space-x-2 absolute bottom-4 left-1/2 transform -translate-x-1/2")
              button(
                  v-for="(slide, index) in slides"
                  :key="slide._id"
                  @click="goToSlide(index)"
                  :class="currentIndex === index ? 'bg-white' : 'bg-white bg-opacity-50'"
                  class="w-3 h-3 rounded-full transition-all"
              )
    

[controls] (кастомные кнопки управления)

  • Описание: Слот для кастомных кнопок управления
  • Props: { nextSlide: Function, prevSlide: Function }
  • Пример:

    imageslider(:slides="slides")
      template([controls]="{ nextSlide, prevSlide }")
          div(class="absolute inset-y-0 left-0 flex items-center")
              button(@click="prevSlide" class="ml-4 p-2 bg-black bg-opacity-50 text-white rounded-full")
                  icon(name="chevron-left")
          div(class="absolute inset-y-0 right-0 flex items-center")
              button(@click="nextSlide" class="mr-4 p-2 bg-black bg-opacity-50 text-white rounded-full")
                  icon(name="chevron-right")
    

Методы компонента

nextSlide()

  • Описание: Переход к следующему слайду
  • Пример использования:

    imageslider(ref="slider" :slides="slides")
    
    @$refs.slider.nextSlide()
    

prevSlide()

  • Описание: Переход к предыдущему слайду
  • Пример использования:

    @$refs.slider.prevSlide()
    

goToSlide(index)

  • Описание: Переход к конкретному слайду по индексу
  • Параметры: index: Number
  • Пример использования:

    @$refs.slider.goToSlide(2) # Переход к третьему слайду
    

play()

  • Описание: Запуск автоматической прокрутки
  • Пример использования:

    @$refs.slider.play()
    

pause()

  • Описание: Приостановка автоматической прокрутки
  • Пример использования:

    @$refs.slider.pause()
    

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

1. Главный слайдер на homepage

imageslider(
    :slides="_.appState.slides"
    :autoplay="true"
    :interval="5000"
    :height="'600px'"
    :show-indicators="true"
    :show-controls="true"
    @slide-change="trackSlideView"
    class="rounded-lg shadow-xl"
)

2. Слайдер мероприятий с кастомным контентом

imageslider(
    :slides="eventSlides"
    :autoplay="false"
    :show-indicators="false"
    class="event-slider"
)
    template([slide]="{ slide, index, active }")
        div(class="relative h-80 rounded-lg overflow-hidden shadow-lg")
            img(
                :src="getText(slide.image)" 
                :alt="getText(slide.title)"
                class="w-full h-full object-cover"
            )
            div(class="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent flex items-end")
                div(class="p-6 text-white")
                    h3(class="text-xl font-bold mb-2") {{ getText(slide.title) }}
                    p(class="text-gray-200 mb-4") {{ getText(slide.content) }}
                    app-link(
                        :to="getText(slide.slide_data.button_link)"
                        class="inline-block bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 transition-colors"
                    ) {{ getText(slide.slide_data.button_text) }}

3. Мини-слайдер товаров

imageslider(
    :slides="productSlides"
    :height="'300px'"
    :show-controls="false"
    :autoplay="true"
    :interval="3000"
    class="product-slider"
)
    template([indicators]="{ slides, currentIndex, goToSlide }")
        div(class="flex justify-center space-x-1 mt-4")
            button(
                v-for="(slide, index) in slides"
                :key="slide._id"
                @click="goToSlide(index)"
                :class="currentIndex === index ? 'w-8 bg-blue-600' : 'w-2 bg-gray-300'"
                class="h-2 rounded-full transition-all duration-300"
            )

4. Fullscreen слайдер галереи

imageslider(
    :slides="gallerySlides"
    :autoplay="false"
    :transition="'fade'"
    :height="'100vh'"
    class="gallery-slider"
)
    template([controls]="{ nextSlide, prevSlide }")
        div(class="absolute inset-0 flex items-center justify-between pointer-events-none")
            button(
                @click="prevSlide"
                class="pointer-events-auto ml-8 p-4 bg-black bg-opacity-50 text-white rounded-full hover:bg-opacity-70 transition-opacity"
            )
                icon(name="arrow-left" class="w-6 h-6")
            button(
                @click="nextSlide"
                class="pointer-events-auto mr-8 p-4 bg-black bg-opacity-50 text-white rounded-full hover:bg-opacity-70 transition-opacity"
            )
                icon(name="arrow-right" class="w-6 h-6")

5. Слайдер с текстовым оверлеем

imageslider(:slides="slidesWithOverlay")
    template([slide]="{ slide, active }")
        div(class="relative h-full")
            img(
                :src="getText(slide.image)"
                :alt="getText(slide.title)"
                class="w-full h-full object-cover"
            )
            div(
                v-if="slide.slide_data.overlay"
                :style="{
                    backgroundColor: 'rgba(0,0,0,' + (slide.slide_data.overlay_opacity || 0.4) + ')'
                }"
                class="absolute inset-0 flex items-center justify-center"
            )
                div(
                    :class="'text-' + (getText(slide.slide_data.text_position) || 'center')"
                    :style="{ color: getText(slide.slide_data.text_color) || '#ffffff' }"
                    class="max-w-2xl px-8"
                )
                    h2(class="text-4xl font-bold mb-4") {{ getText(slide.title) }}
                    p(class="text-xl mb-6") {{ getText(slide.content) }}
                    app-link(
                        v-if="getText(slide.slide_data.button_text)"
                        :to="getText(slide.slide_data.button_link)"
                        :class="getButtonStyle(slide.slide_data.button_style)"
                        class="inline-block px-8 py-3 rounded-lg font-semibold transition-colors"
                    ) {{ getText(slide.slide_data.button_text) }}

Интеграция с мультиязычной системой

Использование с MultilingualData

imageslider(:slides="multilingualSlides")
    template([slide]="{ slide }")
        div(class="relative h-full")
            img(
                :src="AppDB.multilingual.getText(slide.image)"
                :alt="AppDB.multilingual.getText(slide.title)"
                class="w-full h-full object-cover"
            )
            div(class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black to-transparent p-6")
                h3(class="text-white text-2xl font-bold mb-2") 
                    | {{ AppDB.multilingual.getText(slide.title) }}
                p(class="text-gray-200") 
                    | {{ AppDB.multilingual.getText(slide.content) }}

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

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

methods:
    onSlideChange: (data) ->
        # data: { currentSlide: Object, index: Number }
        analytics.track('slide_view', {
            slide_id: data.currentSlide._id
            slide_index: data.index
            slide_title: AppDB.multilingual.getText(data.currentSlide.title)
        })
    
    onSlideClick: (data) ->
        # data: { slide: Object, index: Number }
        if data.slide.slide_data?.button_link
            EventBus.emit('slide_button_click', {
                slide: data.slide
                button_text: AppDB.multilingual.getText(data.slide.slide_data.button_text)
                button_link: AppDB.multilingual.getText(data.slide.slide_data.button_link)
            })

Кастомизация стилей

CSS переменные для кастомизации

.image-slider
    --slider-height: 400px
    --slider-transition-duration: 0.5s
    --indicator-size: 12px
    --indicator-active-color: #3B82F6
    --indicator-inactive-color: #9CA3AF
    --control-size: 48px
    --control-bg: rgba(0, 0, 0, 0.5)
    --control-color: #FFFFFF

Кастомные темы

// Темная тема
.image-slider--dark
    --indicator-active-color: #60A5FA
    --indicator-inactive-color: #4B5563
    --control-bg: rgba(255, 255, 255, 0.1)
    --control-color: #F9FAFB

// Минималистичная тема
.image-slider--minimal
    --indicator-size: 8px
    --control-size: 40px
    --control-bg: transparent
    --control-color: #1F2937
    
    .image-slider__control
        border: 1px solid #E5E7EB

Best Practices

1. Оптимизация изображений

imageslider(:slides="optimizedSlides")
    template([slide]="{ slide }")
        div(class="relative h-full")
            img(
                :src="getOptimizedImage(slide.image)"
                :alt="getText(slide.title)"
                loading="lazy"
                class="w-full h-full object-cover"
            )

2. Обработка ошибок загрузки

imageslider(:slides="slides")
    template([slide]="{ slide }")
        div(class="relative h-full")
            img(
                :src="getText(slide.image)"
                :alt="getText(slide.title)"
                @error="handleImageError"
                class="w-full h-full object-cover"
            )

3. Доступность (Accessibility)

imageslider(
    :slides="slides"
    aria-label="Галерея изображений"
    role="region"
)

4. Производительность

imageslider(
    :slides="lazyLoadedSlides"
    :autoplay="isVisible"
    @slide-change="preloadNextSlide"
)

Отладка и разработка

Логирование состояния

# В родительском компоненте
mounted: ->
    EventBus.on 'slide_change', (data) ->
        debug.log "Слайд изменен: "+data.index
        
    EventBus.on 'slider_autoplay_status', (data) ->
        debug.log "Автопрокрутка: "+(data.playing ? 'включена' : 'выключена')

Валидация данных слайдов

computed:
    validatedSlides: ->
        return @slides.filter (slide) ->
            slide.image? and 
            slide.image.length > 0 and
            slide.slide_data?.active isnt false

Компонент ImageSlider предоставляет богатый функционал для создания адаптивных, доступных и производительных слайдеров с полной поддержкой мультиязычности и кастомизации.