Прокрутка по движению мыши

У меня есть div в моем html, и я добавил overflow: scroll. Я хочу, чтобы он прокручивался в соответствии с движением мыши. Если мышь находится в левой части экрана, прокрутка должна быть в начале. Если мышь находится в центре экрана, прокрутка должна быть в центре, и то же самое касается права. Загляните на этот сайт . Вы должны увидеть верхнюю панель навигации с миниатюрами, которая прокручивается в соответствии с движениями мыши. Я хочу точно такой же эффект. Я построил его, но он не работает, как ожидалось. Если моя мышь находится в центре экрана, полоса прокрутки находится не в центре, а справа. посмотри. Ниже мой код:

const gallery = document.getElementById('gallery');
const activeImage = document.getElementById('active-image');
const thumbnail = document.querySelector('.thumbnail');
const thumbnailWrapper = document.getElementById('thumbnail-wrapper');

thumbnailWrapper.addEventListener('mouseenter', handleMouseMove);
thumbnailWrapper.addEventListener('mousemove', handleMouseMove);

function handleMouseMove(e) {
  const noOfPics = Array.from(thumbnailWrapper.childNodes).length
  const clientX = e.clientX;
  const clientY = e.clientY;
  const width = window.innerWidth;
  const height = window.innerHeight;
  const wrapperWidth = thumbnail.clientWidth * noOfPics;
  const wrapperHeight = thumbnailWrapper.clientHeight;
  const percentX = clientX / width * 100;
  const percentY = clientY / height * 100;
  const scrollX = (wrapperWidth - width) * percentX / 100 - width / 2;
  thumbnailWrapper.scroll(scrollX, 0)
}
* {
  box-sizing: border-box;
  padding: 0%;
  margin: 0%;
}

#gallery {
  width: 100vw;
  height: 100vh;
  background-color: #303030;
  display: flex;
  flex-direction: column;
}

#thumbnail-wrapper {
  display: flex;
  /* justify-content: center; */
  overflow-x: scroll;
  padding: 0.5rem 1rem;
}

#thumbnail-wrapper::-webkit-scrollbar {
  /* display: none; */
  background-color: #000;
}

::-webkit-scrollbar-thumb {
  background: red;
}

.thumbnail {
  flex: none;
  width: 150px;
  height: 100px;
  border: 3px solid #303030;
  background-color: #202020;
  border-radius: 10px;
}

#active-image {
  flex: 1;
  position: relative;
  margin: 1rem;
}

.overflow-hidden {
  overflow: hidden;
}

.overflow-scroll {
  overflow: scroll;
}

.fit {
  height: 100%;
  margin: 0 auto;
}

.original {
  height: auto;
  position: absolute;
  top: 0%;
}
<div id = "gallery">
  <div id = "thumbnail-wrapper">
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
  </div>
  <div id = "active-image" class = "overflow-scroll">
    <img src = "https://www.lifewire.com/thmb/_cH2YBd-iyPP1cqqj2WWXiCWudg=/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/hdwallpapersnet-free-wallpaper-5919d3ca3df78cf5fa49bda3.jpg" alt = "something went wrong" class = "original">
  </div>
</div>

Я думаю, что я неправильно вычисляю scrollX, я пробовал много комбинаций, но не могу получить ожидаемое поведение.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Так что в основном это линейная вещь, начиная с (0, 0) до (clientWidth, maxScroll). Итак, я рассчитываю линейную формулу, тогда легко добавить clientX и получить offsetX.

Возможно, потребуется некоторая настройка по краям. Вероятно, вычислите уравнение от 0+imageWidth до maxWidth-imageWidth. Поиграйте с этим.

Обновление: я играл с ним. Теперь должно быть идеально.

function getLinearFunction(x1, y1, x2, y2) {
  var slope = (y2 - y1) / (x2 - x1);
  return function(x) {
    return slope * (x - x1) + y1;
  }
}


const gallery = document.getElementById('gallery');
const thumbnail = document.querySelector('.thumbnail');
const thumbnailWrapper = document.getElementById('thumbnail-wrapper');

thumbnailWrapper.addEventListener('mousemove', handleMouseMove);
// document.addEventListener('key')

function handleMouseMove(e) {
  const noOfPics = Array.from(thumbnailWrapper.childNodes).length
  const clientX = e.clientX;
  const clientY = e.clientY;
  const width = thumbnailWrapper.clientWidth;
  const height = thumbnailWrapper.clientHeight;
  const wrapperWidth = thumbnail.clientWidth * noOfPics;
  const wrapperHeight = thumbnailWrapper.clientHeight;
  const percentX = clientX / width * 100;
  const percentY = clientY / height * 100;
  const scrollLeft = thumbnailWrapper.scrollLeft
  var maxScrollLeft = thumbnailWrapper.scrollWidth - thumbnailWrapper.clientWidth;
  // when clientX = 0 you want scrollx = 0
  // when clientx = width you want scrollX = maxScrollLeft
  var foo = getLinearFunction(0, 0, width, maxScrollLeft);

  // EDIT: improvement: 
  var foo = getLinearFunction(0 + 150, 0, width - 150, maxScrollLeft);

  output.innerHTML = JSON.stringify({
    clientX,
    clientY,
    width,
    height,
    wrapperWidth,
    wrapperHeight,
    scrollLeft,
    maxScrollLeft
  }, null, 4)

  thumbnailWrapper.scroll(foo(clientX), 0)
}
* {
  box-sizing: border-box;
  padding: 0%;
  margin: 0%;
}

#gallery {
  width: 100vw;
  background-color: #303030;
  display: flex;
  flex-direction: column;
}

#thumbnail-wrapper {
  display: flex;
  /* justify-content: center; */
  overflow-x: scroll;
  padding: 0.5rem 1rem;
  background: yellow;
}

#thumbnail-wrapper::-webkit-scrollbar {
  /* display: none; */
  background-color: #000;
}

::-webkit-scrollbar-thumb {
  background: red;
}

.thumbnail {
  flex: none;
  width: 150px;
  height: 100px;
  border: 3px solid #303030;
  background-color: #202020;
  border-radius: 10px;
}

#active-image {
  flex: 1;
  position: relative;
  margin: 1rem;
}

.overflow-hidden {
  overflow: hidden;
}

.overflow-scroll {
  overflow: scroll;
}

.fit {
  height: 100%;
  margin: 0 auto;
}

.original {
  height: auto;
  position: absolute;
  top: 0%;
}
<div id = "gallery">
  <div id = "thumbnail-wrapper">
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
    <div class = "thumbnail"></div>
  </div>
</div>
<pre id = "output"></pre>

Да, это прекрасно. Хотя я все еще не могу понять это, но пойму это после того, как завершу проект. Уже поздно доставлять это :)

Zohaib Khan 08.02.2023 17:23

Если вы не возражаете, не могли бы вы занять секунду, чтобы объяснить мне, как это работает. Извините, я младший разработчик, это мой первый месяц на моей первой работе в качестве разработчика.

Napstar 08.02.2023 17:44

см., нет никаких оснований полагать, что движение полосы прокрутки нелинейно. я имею в виду, что он прокручивается прямо с той же скоростью, а не быстрее в тот или иной момент. линейный. поэтому, если в одной точке (мышь x) вы знаете значение, которое она должна прокручивать (y), и вы знаете его в другой точке, то вы можете указать все точки, потому что между двумя точками есть ровно одна прямая линия. ну у нас 2 очка. 0, 0 — левая сторона. правая сторона (maxX, maxY), где maxX — максимальная мышь, а maxY — максимальная прокрутка. так что в целом вы должны знать, что можете рассчитать все точки между использованием формулы ax+b=y

IT goldman 08.02.2023 18:49

Ааааа, это гениально, я рассчитывал, сколько он прокручивает, когда мышь находится в точке x. Я не думал о скорости. Спасибо

Napstar 08.02.2023 21:23

Другие вопросы по теме