Cómo crear un carrusel arrastrable usando Vanilla JavaScript

El carrusel o control deslizante de un sitio web es una forma efectiva de mostrar varias imágenes o contenido en un solo espacio. Alienta a los visitantes a concentrarse en lo importante...

Introducción

El carrusel o control deslizante de un sitio web es una forma efectiva de mostrar múltiples imágenes o contenido en un solo espacio. Alienta a los visitantes a concentrarse en el contenido importante del sitio web y, al mismo tiempo, mejora el atractivo visual general al ahorrar espacio en la pantalla.

En este artículo, aprenderemos cómo crear un carrusel que se pueda arrastrar desde cero usando JavaScript estándar. Esto será muy detallado y explicativo para que todos puedan entenderlo.

{.icon aria-hidden=“true”}

Nota: El código fuente está disponible en GitHub.

Comenzando

Para construir el carrusel arrastrable desde cero en JavaScript estándar, necesitaríamos usar un conjunto de eventos de mouse únicos, como:

  • mousedown: cuando se presiona un botón del mouse mientras el puntero está dentro de un elemento, se activa el evento mousedown.
  • mouseenter: cuando se mueve el mouse por primera vez a un elemento, se activa el evento mouseenter.
  • mouseleave: cuando el cursor de un mouse se mueve fuera de un elemento, se activa el evento mouseeleave (esto es lo opuesto a mouseenter).
  • mouseup: El evento mouseup se activa cuando el puntero está dentro del elemento y se suelta un botón del ratón.
  • mousemove: cuando se mueve un mouse mientras el cursor está dentro de él, se activa el evento movemouse.

Comencemos por crear nuestro archivo HTML; básicamente, tendríamos tantas tarjetas como queramos con el contenido que queramos. Para evitar pegar código HTML de más de 80 líneas, eliminaría el contenido de las tarjetas y preferiría usar cuadros:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<div class="slider-container">
    <div class="inner-slider">
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
    </div>
</div>

Agreguemos también algunos estilos básicos a slider-container, inner-slider y card:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.card {
    height: 300px;
    width: 400px;
    border-radius: 5px;
}
.card:nth-child(odd) {
    background-color: blue;
}
.card:nth-child(even) {
    background-color: rgb(0, 183, 255);
}
.slider-container {
    width: 80%;
    height: 350px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    overflow: hidden;
}
.inner-slider {
    width: 150%;
    display: flex;
    gap: 10px;
    pointer-events: none;
    position: absolute;
    top: 0;
    left: 0;
}

{.icon aria-hidden=“true”}

Nota: overflow: hidden; se agregó a slider-container, por lo que oculta las otras tarjetas que están fuera del ancho especificado. También usamos posición: absoluta; junto con arriba y izquierda en el control deslizante interno, por lo que podemos hacer uso de la posición izquierda más adelante con JavaScript.

En este punto, su página debería verse así:

Hacer que el carrusel se pueda arrastrar {#hacer que el carrusel se pueda arrastrar}

El primer paso será seleccionar el elemento deslizante, el propio control deslizante y el contenedor del control deslizante. Luego configuraremos tres variables que usaremos más adelante.

1
2
3
4
5
6
let sliderContainer = document.querySelector('.slider-container');
let innerSlider = document.querySelector('.inner-slider');

let pressed = false;
let startX;
let x;

Como se indicó anteriormente, utilizaremos una gran cantidad de eventListeners del mouse para manejar varias operaciones. En su mayoría, los adjuntaremos al elemento deslizante principal.

El primer evento que observaremos es el evento mousedown, que es similar pero no exactamente igual a un clic. Aquí es donde especificaremos lo que queremos que suceda cuando un usuario haga clic en el contenedor del control deslizante.

{.icon aria-hidden=“true”}

Nota: Esto difiere del evento clic en que el evento clic se activa después de que se haya producido una acción de clic completo; es decir, se presiona y suelta el botón del mouse mientras el puntero permanece dentro del mismo elemento. Mientras que, el mousedown se ejecuta en el momento en que se presiona el botón por primera vez.

1
2
3
sliderContainer.addEventListener('mousedown', () => {
    ...
})

Para demostrar que la variable presionada, que previamente inicializamos como falso, está presionada, primero le asignaremos verdadero. También estableceremos el valor de startx en el valor de compensación en la dirección x menos el valor de compensación de innerSlider en la izquierda, que actualmente es 0. Podemos ver lo que esto significa al intentar desconectar el valor de startx.

También diseñaremos el cursor para una mejor interacción. Esto se establecerá en “agarrar” (para verificar lo que hace, intente hacer clic dentro del “contenedor deslizante”).

1
2
3
4
5
sliderContainer.addEventListener("mousedown", (e) => {
    pressed = true;
    startX = e.offsetX - innerSlider.offsetLeft;
    sliderContainer.style.cursor = "grabbing";
});

El próximo evento que buscaríamos es mouseenter; estamos haciendo esto para agregar interactividad básica diseñando el cursor para indicar que se ha tomado el control deslizante o una tarjeta deslizante específica.

1
2
3
sliderContainer.addEventListener("mouseenter", () => {
    sliderContainer.style.cursor = "grab";
});

Después de eso, escucharíamos el evento mouseup y estableceríamos el estilo cursor en grab, de modo que cuando un usuario deje de agarrar o hacer clic, el cursor cambiaría de nuevo a grab en lugar de grabbing . También devolveremos el valor presionado a falso.

1
2
3
4
sliderContainer.addEventListener("mouseup", () => {
    sliderContainer.style.cursor = "grab";
    pressed = false;
});

Hemos podido agregar algo de interactividad hasta este punto, pero aún no hemos implementado la funcionalidad principal, un carrusel que se puede arrastrar.

Manejo de la lógica central

Ahora ocupémonos de la lógica central; Seguiremos apuntando al sliderContainer, pero esta vez estaremos escuchando un evento mousemove. En la función de devolución de llamada, verificaríamos si presionado es falso para poder devolver la función, y no haría nada.

1
2
3
4
sliderContainer.addEventListener("mousemove", (e) => {
    if (!pressed) return;
    ...
});

Pero, si presionado es verdadero, podemos proceder a otras lógicas. El primer paso será evitar los comportamientos predeterminados, seguido de establecer x en offsetX (la coordenada x del puntero del mouse en relación con el elemento deslizante del contenedor).

1
2
3
4
5
6
sliderContainer.addEventListener("mousemove", (e) => {
    if (!pressed) return;
    e.preventDefault();

    x = e.offsetX;
});

Notarás que cuando diseñamos la clase CSS innerSlider, agregamos posición: absoluta y un valor izquierda de 0. Ahora vamos a cambiar el valor left a x-startX dinámicamente cuando el usuario arrastra el carrusel. (estamos restando nuestra posición actual del desplazamiento del div principal).

1
2
3
4
5
6
7
8
sliderContainer.addEventListener("mousemove", (e) => {
    if (!pressed) return;
    e.preventDefault();

    x = e.offsetX;

    innerSlider.style.left = `${x - startX}px`;
});

En este punto, notará que todo funciona bien porque nuestro control deslizante ahora se arrastra correctamente, pero no hay límite en cuanto a dónde puede detenerse el desplazamiento.

Cuidémoslo ahora definiendo una nueva función. Lo primero será obtener la posición de los contenedores deslizantes interno y externo, luego ahora podemos crear dos declaraciones condicionales para que funcionen para ambos lados.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const checkBoundary = () => {
    let outer = sliderContainer.getBoundingClientRect();
    let inner = innerSlider.getBoundingClientRect();

    if (parseInt(innerSlider.style.left) > 0) {
        innerSlider.style.left = "0px";
    }

    if (inner.right < outer.right) {
        innerSlider.style.left = `-${inner.width - outer.width}px`;
    }
};

Una vez hecho esto, ahora podemos llamar a esta función dentro del detector de eventos mousemove como lo último:

1
2
3
4
sliderContainer.addEventListener("mousemove", (e) => {
    ...
    checkBoundary();
});

Pudimos crear con éxito un control deslizante arrastrable con JavaScript desde cero usando este método.

Conclusión

En este artículo, aprendimos cómo crear un carrusel arrastrable desde cero usando JavaScript estándar, también aprendimos la diferencia entre todos los eventos del mouse utilizados. os.