Карусель при наведении курсора на контент

секция в котором находятся блоки, которые при наведении по левой стороне секции должны скролиться влево, соответственно и право тоже.

Перерыл много чего в интернете и так не смог найти решения данной проблемы. Написал бы сам на js, но не так силен в нем:(


Ответы (2 шт):

Автор решения: Oliver Patterson

Решил реализовать чисто ради интереса, но я думаю с этой задачей справился и ГПТ.
В объяснении кода я не сильно силен, но некоторые вещи пометил комментариями.

Не считаю свое решение идеальным.

class AutoScroller
{
    HOVER_CURSOR_ZONE = 100; // Размер зоны для наведения по краям
    SCROLL_DISTANCE = 100; // Расстояние, на которое прокручивает
    SCROLL_SPEED = 100; // Количество мс между автоматическим скролом

    #scrollTimerId;
    #wrapper;

    constructor(wrapperSelector)
    {
        this.#wrapper = document.querySelector(wrapperSelector);

        this.#init();
    }

    #init()
    {
        if (this.#wrapper === null)
        {
            console.error("Wrapper not found");
            return;
        }

        this.#wrapper.addEventListener("mouseleave", () => this.#stopScrolling());
        this.#wrapper.addEventListener("mousemove", (event) => this.#handleMouseMove(event));
    }

    #handleMouseMove(event)
    {
        const { clientWidth } = this.#wrapper;
        let direction = 0; // -1 - left | 0 - none | 1 - right

        // Проверяем, попадает ли курсор в зону наведения
        if (event.clientX >= clientWidth - this.HOVER_CURSOR_ZONE)
        {
            direction = 1; // Двигаем вправо
        }
        else if (event.clientX <= this.HOVER_CURSOR_ZONE)
        {
            direction = -1; // Двигаем влево
        }

        if (this.#scrollTimerId)
        {
            this.#stopScrolling();
        }

        if (direction !== 0)
        {
            this.#scrollingBlock(direction);
            this.#scrollTimerId = setInterval(() => this.#scrollingBlock(direction), this.SCROLL_SPEED);
        }
    }

    #scrollingBlock(direction)
    {
        if (!this.#wrapper)
        {
            return;
        }

        this.#wrapper.scrollTo({
            left: this.#wrapper.scrollLeft + (this.SCROLL_DISTANCE * direction),
            behavior: "smooth"
        });
    }

    #stopScrolling()
    {
        clearInterval(this.#scrollTimerId);
        this.#scrollTimerId = undefined;
    }
}

const autoScroller = new AutoScroller(".wrapper");
.wrapper
{
    display: flex;
    gap: 8px;

    overflow-x: auto;

    div
    {
        width: 300px;
        height: 150px;

        flex-shrink: 0;

        background-color: #DC4242;
        border-radius: 16px;
    
    display: grid;
    place-content: center;
    
    color: #FFF;
    font-size: 3em;
    }
}

.wrapper::-webkit-scrollbar
{
    height: 0px !important;
}
<div class="wrapper">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
    <div>10</div>
    <div>11</div>
    <div>12</div>
    <div>13</div>
    <div>14</div>
    <div>15</div>
    <div>16</div>
    <div>17</div>
    <div>18</div>
    <div>19</div>
    <div>20</div>
</div>

→ Ссылка
Автор решения: Owlly

const scrollContainer = document.querySelector('.scroll-container');
let scrollSpeed = 0;
let scrollInterval;

scrollContainer.addEventListener('mousemove', (e) => {
  const containerWidth = scrollContainer.offsetWidth;
  const mouseX = e.clientX - scrollContainer.getBoundingClientRect().left;
  const scrollLeftMax = scrollContainer.scrollWidth - containerWidth;

  // Наведение на левый край 20%
  if (mouseX < containerWidth * 0.2) {
    scrollSpeed = -5; // Скорость прокрутки влево
  }
  // Наведение на правый край 20%
  else if (mouseX > containerWidth * 0.8) {
    scrollSpeed = 5; // Скорость прокрутки вправо
  }
  // Остановка прокрутки в центре
  else {
    scrollSpeed = 0;
  }
});

scrollContainer.addEventListener('mouseleave', () => {
  scrollSpeed = 0;
});

scrollInterval = setInterval(() => {
  if (scrollSpeed !== 0) {
    scrollContainer.scrollLeft += scrollSpeed;
  }
}, 16);
.scroll-container {
  width: 100%;
  overflow: hidden;
  position: relative;
}

.scroll-content {
  display: flex;
  transition: transform 0.3s ease;
  white-space: nowrap;
  width: fit-content;
}

.block {
  width: 300px;
  margin: 0 10px;
  background-color: #ccc;
  text-align: center;
  line-height: 150px;
  height: 150px;
  display: inline-block;
}
<div class="scroll-container">
  <div class="scroll-content">
    <div class="block">Блок 1</div>
    <div class="block">Блок 2</div>
    <div class="block">Блок 3</div>
    <div class="block">Блок 4</div>
    <div class="block">Блок 5</div>
    <div class="block">Блок 6</div>
    <div class="block">Блок 7</div>
    <div class="block">Блок 8</div>
  </div>
</div>

→ Ссылка