Skip to content

useCarousel

Este composable de Vue (useCarousel) encapsula y organiza la lógica necesaria para controlar un carrusel utilizando el componente Swiper. Expone funciones para:

  • Establecer el carrusel.

  • Cambiar de slide de forma controlada.

  • Prevenir animaciones múltiples.

  • Compartir estos datos con otros componentes mediante provide.

// Importa el tipo SwiperContainer desde el bundle de Swiper (versión basada en Web Components)
import { type SwiperContainer } from 'swiper/element/bundle'
// Composable de Vue que encapsula la lógica de un carrusel basado en Swiper
export function useCarousel() {
// Duración de la animación en milisegundos
const ANIMATION_DURATION = 300
// Referencia al contenedor del carrusel (SwiperContainer)
const carousel = ref<SwiperContainer>()
// ID del tab o slide actualmente activo
const tabId = ref(0)
// Booleano para evitar múltiples animaciones simultáneas
const isAniming = ref(false)
// Función para actualizar la referencia del carrusel
const valueCarousel = (newCarousel: SwiperContainer) => {
carousel.value = newCarousel
}
// Función para trasladar el carrusel a un nuevo slide (itemId)
const translateCarousel = (itemId: number) => {
// Si ya está animando, no se hace nada
if (isAniming.value) return
// Se marca como animando
isAniming.value = true
// Se obtiene la instancia interna de Swiper desde el Web Component
const slider = carousel.value?.swiper
if (!slider) return
// Se actualiza el ID del tab activo
tabId.value = itemId
// Se desplaza el carrusel al nuevo slide con duración definida
slider.slideTo(itemId, ANIMATION_DURATION)
// Después de que termine la animación, se habilitan nuevas animaciones
setTimeout(() => {
isAniming.value = false
}, ANIMATION_DURATION)
}
// Se proporcionan las funciones y variables reactivas para que otros componentes las puedan inyectar (dependency injection)
provide('translateCarousel', translateCarousel)
provide('valueCarousel', valueCarousel)
provide('tabId', tabId)
provide('isAniming', isAniming)
// Se retorna el estado y funciones del carrusel para su uso local
return {
carousel, // Referencia al contenedor del carrusel (SwiperContainer)
translateCarousel, // Función para trasladar el carrusel a un nuevo slide (itemId)
valueCarousel, // Función para actualizar la referencia del carrusel
tabId, // ID del tab o slide actualmente activo
isAniming // Booleano para evitar múltiples animaciones simultáneas
}
}

Ejemplo de uso con componentes de ejemplo:

Section titled “Ejemplo de uso con componentes de ejemplo:”
<script setup lang="ts">
import { useCarousel } from "@/composables/useCarousel";
import { onMounted } from "vue";
// Usa el composable
const { carousel, valueCarousel, translateCarousel, tabId, isAniming } =
useCarousel();
// Este `onMounted` es solo si necesitas hacer algo al montar el carrusel
onMounted(() => {
console.log("Carrusel montado, tab activo:", tabId.value);
});
</script>
<template>
<swiper-container
init="false"
ref="carousel"
@swiper="valueCarousel"
slides-per-view="1"
speed="300"
loop
>
<swiper-slide>Slide 1</swiper-slide>
<swiper-slide>Slide 2</swiper-slide>
<swiper-slide>Slide 3</swiper-slide>
</swiper-container>
<div class="buttons">
<button @click="translateCarousel(0)">Ir a Slide 1</button>
<button @click="translateCarousel(1)">Ir a Slide 2</button>
<button @click="translateCarousel(2)">Ir a Slide 3</button>
</div>
<!-- Componente hijo que consume el contexto -->
<SlideStatus />
</template>
<script setup lang="ts">
import { inject } from "vue";
const tabId = inject("tabId");
const isAniming = inject("isAniming");
// Type-safety opcional
if (!tabId || !isAniming) {
throw new Error("useCarousel not provided");
}
</script>
<template>
<p>Slide activo: {{ tabId }}</p>
<p v-if="isAniming">Animando...</p>
</template>