es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Desplazamiento con javascript y div con propiedad ‘position: sticky’

Tengo una aplicación de React que básicamente es un contenedor con 2 columnas. La columna izquierda es una lista y la columna derecha es un div con posición fija (en realidad es un mapa con pines. Debe mantenerse fijo en la pantalla). Cada elemento de la lista es un enlace en la columna derecha. Cuando el usuario hace clic en el título, la pantalla debe desplazarse para mostrar el elemento actual de la lista en la columna izquierda.

El problema es que cuando la pantalla se desplaza hacia un elemento al final de la lista, la columna derecha también se desplaza y no se mantiene fija.

Me gustaría mantener la columna derecha siempre fija cuando el usuario haga clic en algún título, independientemente de la posición del elemento en la lista de la columna izquierda.
¿Alguna idea de cómo solucionarlo?

Imagen 1

Imagen 2

Imagen 3

Enlace al código

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Solución para mantener la columna derecha fija en una aplicación de React

    Problema

    El problema con la aplicación de React actual es que cuando la pantalla se desplaza hacia un elemento al final de la lista, la columna derecha también se desplaza y no se mantiene fija.

    Solución

    Para solucionar este problema, debemos realizar algunos cambios en el código de la aplicación. Aquí están los pasos:

    1. Necesitamos mover el elemento pegajoso (el mapa con pines) fuera de la columna y convertirlo en un componente separado.
    2. Debemos pasar una propiedad al componente pegajoso para identificar el elemento activo actual.

    3. El componente pegajoso debe utilizar la propiedad pasada y actualizar su posición basándose en el elemento activo.

    4. Debemos envolver la lista con un elemento contenedor y agregar un evento onScroll al mismo.

    5. Cuando el usuario hace clic en el título de un elemento de la lista, debemos desplazar el contenedor hasta la posición adecuada.

    6. Cuando el contenedor se desplaza, debemos actualizar el elemento activo en el componente pegajoso basándonos en la posición de desplazamiento del contenedor.

    Aquí tienes un código de ejemplo que implementa los cambios mencionados:

    import React, { useState, useRef, useEffect } from "react";
    import StickyMap from "./StickyMap";
    
    const data = [
      { id: 1, title: "Elemento 1" },
      { id: 2, title: "Elemento 2" },
      { id: 3, title: "Elemento 3" },
      { id: 4, title: "Elemento 4" },
      { id: 5, title: "Elemento 5" },
      { id: 6, title: "Elemento 6" },
      { id: 7, title: "Elemento 7" },
      { id: 8, title: "Elemento 8" }
    ];
    
    const App = () => {
      const [activeItem, setActiveItem] = useState(null);
      const listRef = useRef(null);
    
      const handleItemClick = id => {
        const item = document.getElementById(`item-${id}`);
        listRef.current.scrollTo({
          top: item.offsetTop,
          behavior: "smooth"
        });
      };
    
      const handleListScroll = () => {
        const listItems = document.getElementsByClassName("list-item");
        for (let i = 0; i < listItems.length; i++) {
          if (
            listItems[i].offsetTop - listRef.current.scrollTop <=
            window.innerHeight / 2
          ) {
            setActiveItem(Number(listItems[i].dataset.id));
          }
        }
      };
    
      return (
        <div classname="container">
          <div classname="list-container" ref="{listRef}" onscroll="{handleListScroll}">
            {data.map(item => (
              <div classname="list-item" key="{item.id}" id="{`item-${item.id}`}" data-id="{item.id}" onclick="{()" ==""> handleItemClick(item.id)}
              >
                <h3>{item.title}</h3>
                Algunos detalles sobre este elemento
              </div>
            ))}
          </div>
          <stickymap activeitem="{activeItem}"></stickymap>
        </div>
      );
    };
    
    export default App;
    

    En el código anterior, hemos creado un nuevo componente llamado StickyMap que recibe la propiedad activeItem. Este componente es responsable de renderizar el mapa con los pines y actualizar su posición en base al elemento activo.

    La función handleItemClick es responsable de desplazar el contenedor de la lista hasta la posición adecuada. Encuentra la posición del elemento utilizando item.offsetTop y llama al método scrollTo en el contenedor de la lista.

    La función handleListScroll es responsable de actualizar el elemento activo en el componente pegajoso. Encuentra todos los elementos de la lista utilizando document.getElementsByClassName y recorrelos para encontrar el elemento activo basándose en la posición de desplazamiento del contenedor.

    Finalmente, hemos agregado un evento onScroll al contenedor de la lista para llamar a la función handleListScroll cada vez que el contenedor se desplace.

    Conclusión

    Siguiendo los pasos anteriores y realizando los cambios necesarios en el código de la aplicación, podemos mantener la columna derecha siempre fija cuando el usuario hace clic en algún título, independientemente de la posición del elemento en la lista de la columna izquierda.

Comments are closed.