Карусель при наведении курсора на контент
секция в котором находятся блоки, которые при наведении по левой стороне секции должны скролиться влево, соответственно и право тоже.
Перерыл много чего в интернете и так не смог найти решения данной проблемы. Написал бы сам на 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>