Чистый js. Получить ширину элемента и использовать его в прокрутке

#javascript #html

#javascript #HTML

Вопрос:

В настоящее время я не могу сосредоточиться на чем-то, вероятно, действительно простом.

Чтобы получить хорошее представление, чуть ниже приведен html.

У него есть ползунок с #sliderScroll идентификатором as с фиксированной шириной и прокруткой переполнения.

Внутри есть несколько div.text-image-item блоков, которые представляют собой блоки с размером ширины, который изменяется в зависимости от размера экрана пользователя.

 <div id="sliderScroll" class="slider">
   <div class="text-image-item"> Content block 1 </div>
   <div class="text-image-item"> Content block 2 </div>
   <div class="text-image-item"> Content block 3 </div>
   <div class="text-image-item"> Content block 4 </div>
</div>
  

С помощью кнопки я хочу, чтобы пользователь мог прокручивать по горизонтали.
Я хочу, чтобы количество пикселей для прокрутки представляло ширину блока ( .text-image-item ), которая колеблется в зависимости от размера экрана пользователя.

Я пытаюсь получить ширину этого .text-image-item блока и использовать ее в функции scrollLeft .

Что я получил до сих пор:

 const buttonLeft = document.getElementById('scrollLeft');

buttonLeft.onclick = function () {
    var itemWidth = document.getElementsByClassName('text-image-item').offsetWidth;
    console.log(itemWidth);
    document.getElementById('sliderScroll').scrollLeft -= itemWidth;
};
  

Если я установлю фиксированное число для var itemWidth , похоже, оно работает.
Но я хочу получить ширину div с классом .text-image-item .

Я добавил console.log , чтобы посмотреть, выводит ли var правильное число, но оно только возвращается undefined .

Может кто-нибудь указать мне правильное направление? Я ломаю голову над этим, так как я не совсем уверен, где что-то идет не так.

Комментарии:

1. document.getElementsByClassName('text-image-item') возвращает a NodeList , который в данном случае содержит 4 узла. NodeList У него нет offsetWidth . Ширину имеют только отдельные элементы.

2. Спасибо, Эми. Я не знал, что это не будет работать с несколькими элементами, даже если все они имеют одинаковую ширину.

3. Они не гарантированно имеют одинаковую ширину. Однако, если вы считаете, что это действительно так, просто выберите один из элементов и используйте его ширину.

4. Действительно подойдет.

Ответ №1:

document.getElementsByClassName('text-image-item') возвращает a NodeList , который в данном случае содержит 4 узла. NodeList У него нет offsetWidth . Ширину имеют только отдельные элементы.

Вам нужно будет выбрать один из узлов и вместо этого использовать его ширину. Вы можете сделать это, выбрав допустимый индекс:

 document.getElementsByClassName('text-image-item')[0].offsetWidth
  

Для получения дополнительной информации о NodeList , проверьте MDN

Ответ №2:

document.getElemenetsByClassName() возвращает a NodeList , но вы выполняете операции с ним, поскольку это элемент. Кроме того, похоже, что вам нужен только один из элементов класса .text-image-item , поэтому достаточно использовать document.querySelector() like document.querySelector('.text-image-item') , поскольку он вернет первый элемент с этим именем класса.

Попробуйте:

 const buttonLeft = document.getElementById('scrollLeft');

buttonLeft.onclick = function() {
  let itemWidth = document.querySelector('.text-image-item').offsetWidth;
};  
 <button id="scrollLeft">Scroll Left</button>
<div id="sliderScroll" class="slider">
  <div class="text-image-item"> Content block 1 </div>
  <div class="text-image-item"> Content block 2 </div>
  <div class="text-image-item"> Content block 3 </div>
  <div class="text-image-item"> Content block 4 </div>
</div>  

Ответ №3:

Можно взять элементы, которые у вас есть в прокрутке, до текущего элемента и суммировать их ширину. Затем вы можете использовать это для установки ширины прокрутки. Таким образом, вы можете иметь элементы любой ширины, которые вам нравятся, и все равно добраться до нужного вам элемента.

 const sumByFunction = f => (p, c) => p   f(c);
const getOffsetWidth = element => element.offsetWidth;

const querySelector = element =>
  selector =>
    Array.from(element.querySelectorAll(selector))

const sumOffsetWidths = sumByFunction(getOffsetWidth)

const scrollNext = (element) => {
  let currentScroll = 0;
  const selector = querySelector(element);
  
  return () => {
    currentScroll  ;
    const scrollTarget = selector('.text-image-item')
      .slice(0, currentScroll)
      .reduce(sumOffsetWidths, 0)
      
    element.scrollLeft = scrollTarget;
  }
};

document
  .getElementById('scroller')
  .onclick = scrollNext(document.getElementById('sliderScroll'));  
 #sliderScroll {
  overflow-x: scroll;
  overflow-y: hidden;
  white-space: nowrap;
}

.text-image-item {
  border: solid 2px rgba(20, 20, 30, 0.4);
  display: inline-block;
  width: 70vw;
}

#scroller {
  position: fixed;
  left: 0;
  top: 20vh;
}  
 <div id="sliderScroll" class="slider">
   <div class="text-image-item"> Content block 1 </div>
   <div class="text-image-item" style="width: 2000px; background-color: rgba(50, 100, 200, 0.4);"> Content block 2 </div>
   <div class="text-image-item"> Content block 3 </div>
   <div class="text-image-item"> Content block 4 </div>
</div>
<button id="scroller">Scroll next</button>