Как можно достичь аналогичного эффекта с использованием React?

Как можно реализовать горизонтальный скролл блока на странице, который при достижении конца переключится обратно на вертикальный скролл вниз, используя React? Я думаю, что с простым JavaScript это было бы проще, но не уверен, как это сделать в React. Ссылка на пример: <a href="https://walba-dynamics.com/ru/" rel="nofollow">https://walba-dynamics.com/ru/</a>
  • 30 августа 2024 г. 10:14
Ответы на вопрос 1
Для реализации эффекта, где горизонтальный скролл блока переключается на вертикальный скролл вниз при достижении конца, можно использовать React вместе с хуками и обработчиками событий. Давайте рассмотрим, как это можно сделать.

### Шаги реализации

1. **Создание компонента с горизонтальным скроллом**.
2. **Отслеживание события скролла и изменение направления**.
3. **Переключение обратно на вертикальный скролл**.

### Пример кода

Вот базовый пример, как это можно реализовать:

```jsx
import React, { useRef, useEffect, useState } from 'react';
import './App.css'; // добавьте стили для демонстрации

const App = () => {
  const scrollRef = useRef(null);
  const [isHorizontalScroll, setIsHorizontalScroll] = useState(true);

  const items = Array.from({ length: 20 }, (_, i) => (
    <div className="item" key={i}>
      Item {i + 1}
    </div>
  ));

  useEffect(() => {
    const handleScroll = (e) => {
      if (isHorizontalScroll) {
        e.preventDefault();
        scrollRef.current.scrollLeft += e.deltaY; // Горизонтальный скролл
      }
    };

    const handleScrollEnd = () => {
      const scrollWidth = scrollRef.current.scrollWidth;
      const clientWidth = scrollRef.current.clientWidth;

      // Проверяем достигли ли конца горизонтального скролла
      if (scrollRef.current.scrollLeft + clientWidth >= scrollWidth) {
        setIsHorizontalScroll(false);
        window.scrollTo(0, window.scrollY + 200); // Переключаем на вертикальный скролл
      } else if (scrollRef.current.scrollLeft === 0) {
        setIsHorizontalScroll(true);
        window.scrollTo(0, window.scrollY - 200); // Вернуться вверх
      }
    };

    const ref = scrollRef.current;
    if (ref) {
      ref.addEventListener('wheel', handleScroll);
      ref.addEventListener('scroll', handleScrollEnd);
    }

    return () => {
      if (ref) {
        ref.removeEventListener('wheel', handleScroll);
        ref.removeEventListener('scroll', handleScrollEnd);
      }
    };
  }, [isHorizontalScroll]);

  return (
    <div className="container">
      <div className="horizontal-scroll" ref={scrollRef}>
        {items}
      </div>
    </div>
  );
};

export default App;
```

### Стили (App.css)

```css
.container {
  height: 100vh; /* Высота экрана */
  overflow-y: scroll; /* Вертикальный скролл */
}

.horizontal-scroll {
  display: flex;
  overflow-x: auto; /* Горизонтальный скролл */
  white-space: nowrap;
  height: 200px; /* Высота блока с горизонтальным скроллом */
}

.item {
  width: 200px; /* Ширина элемента */
  height: 100%; /* Высота 100% от родителя */
  border: 1px solid #ccc;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 1rem;
}
```

### Как это работает

1. **Горизонтальное прокручивание**: Используем `e.deltaY` для горизонтального скролла, когда `isHorizontalScroll` равно `true`.
2. **Смена направления скролла**: При достижении конца или начала горизонтального скролла `setIsHorizontalScroll` переключается на `false` или `true`, а затем осуществляется прокрутка страницы вниз или вверх.
3. **Очистка событий**: Не забывайте убирать обработчики событий при размонтировании компонента.

### Заказ рисовки и оптимизация

В реальном приложении потребуется учесть производительность и UX. Можно добавить анимации, плавный переход между прокрутками и более продвинутую логику для определения момента, когда переключаться между прокрутками.
Похожие вопросы