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.
Implementación del Composable:
Section titled “Implementación del Composable:”// 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 Swiperexport 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:”CarouselProvider.vue
Section titled “CarouselProvider.vue”<script setup lang="ts">import { useCarousel } from "@/composables/useCarousel";import { onMounted } from "vue";
// Usa el composableconst { carousel, valueCarousel, translateCarousel, tabId, isAniming } = useCarousel();
// Este `onMounted` es solo si necesitas hacer algo al montar el carruselonMounted(() => { 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>SlideStatus.vue
Section titled “SlideStatus.vue”<script setup lang="ts">import { inject } from "vue";
const tabId = inject("tabId");const isAniming = inject("isAniming");
// Type-safety opcionalif (!tabId || !isAniming) { throw new Error("useCarousel not provided");}</script>
<template> <p>Slide activo: {{ tabId }}</p> <p v-if="isAniming">Animando...</p></template>