在 JavaScript 中将所选项目置于数字选择器小部件内的中心

2024-01-25

[前提]

我很难弄清楚如何制作数字选择器小部件行为类似于移动选择器组件 https://developer.android.com/guide/topics/ui/controls/pickers。如果用户默认分配一个号码,则selected页面加载时,数字应该自动对齐到中心。


[问题]

  • 我怎样才能捕捉这个元素<div class="cell selected">10</div>到的中心滚动端口默认情况下?
  • 不要依赖任何插件。
"use strict";
console.clear();

{
  const selector = "scrollport";
  const selected = "selected";
  const scrollports = document.getElementsByClassName(selector);
  const debouncedFunc = debounce(check, 250);
  for (const scrollport of scrollports) {
    scrollport.addEventListener("scroll", debouncedFunc);
  }

  function check(e) {
    const rect = e.target.getBoundingClientRect();
    const centerCell = document.elementFromPoint(
      rect.left + e.target.offsetWidth / 2,
      rect.top + e.target.offsetHeight / 2
    );
    for (const cell of e.target.getElementsByClassName(selected)) {
      cell.classList.remove(selected);
    }
    centerCell.classList.add(selected);
  }
}

function debounce(func, wait) {
  let timeout;
  return function(...args) {
    const context = this;
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(context, args), wait);
  };
}
* {
  box-sizing: border-box;
  font-family: Roboto, sans-serif;
}

.container {
  display: flex;
  flex-direction: row;
  width: 10rem;
  height: 22rem;
  border-radius: 3rem;
  border: solid 0.2rem #b2b2c2;
  background-color: #000000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.scrollport:before,
.scrollport:after {
  content: '';
}

.scrollport {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  width: 9.4rem;
  height: 22rem;
  overflow: auto;
  scroll-snap-type: y mandatory;
}

.scrollport:before,
.scrollport:after,
.cell {
  display: block;
  scroll-snap-align: center;
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 33.3%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #e9e9f2;
  font-size: 2.4rem;
}

.selected {
  font-size: 3rem;
  font-weight: bold;
  color: #0073e6;
}
<div class="container">
  <div class="scrollport">
    <div class="cell">09</div>
    <div class="cell selected">10</div>
    <div class="cell">11</div>
    <div class="cell">12</div>
    <div class="cell">13</div>
    <div class="cell">14</div>
    <div class="cell">15</div>
    <div class="cell">16</div>
  </div>
</div>

[预期结果]


您可以尝试通过减去所选值来设置父项的滚动位置offsetTop with scrollHeight获得精确的垂直居中位置:

"use strict";
console.clear();

{
  const selector = "scrollport";
  const selected = "selected";
  const scrollports = document.getElementsByClassName(selector);
  const initialValue = document.getElementsByClassName(selected);
  const debouncedFunc = debounce(check, 250);
  for (const scrollport of scrollports) {
    scrollport.addEventListener("scroll", debouncedFunc);
    scrollport.scrollTo({
      top: initialValue[0].offsetTop - initialValue[0].scrollHeight,
      behavior: 'smooth'
    });
  }

  function check(e) {
    const rect = e.target.getBoundingClientRect();
    const centerCell = document.elementFromPoint(
      rect.left + e.target.offsetWidth / 2,
      rect.top + e.target.offsetHeight / 2
    );
    for (const cell of e.target.getElementsByClassName(selected)) {
      cell.classList.remove(selected);
    }
    centerCell.classList.add(selected);
  }
}

function debounce(func, wait) {
  let timeout;
  return function(...args) {
    const context = this;
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(context, args), wait);
  };
}
* {
  box-sizing: border-box;
  font-family: Roboto, sans-serif;
}

.container {
  display: flex;
  flex-direction: row;
  width: 10rem;
  height: 22rem;
  border-radius: 3rem;
  border: solid 0.2rem #b2b2c2;
  background-color: #000000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.scrollport:before,
.scrollport:after {
  content: '';
}

.scrollport {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  width: 9.4rem;
  height: 22rem;
  overflow: auto;
  scroll-snap-type: y mandatory;
}

.scrollport:before,
.scrollport:after,
.cell {
  display: block;
  scroll-snap-align: center;
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 33.3%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #e9e9f2;
  font-size: 2.4rem;
}

.selected {
  font-size: 3rem;
  font-weight: bold;
  color: #0073e6;
}
<div class="container">
  <div class="scrollport">
    <div class="cell">09</div>
    <div class="cell selected">10</div>
    <div class="cell">11</div>
    <div class="cell">12</div>
    <div class="cell">13</div>
    <div class="cell">14</div>
    <div class="cell">15</div>
    <div class="cell">16</div>
  </div>
</div>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 JavaScript 中将所选项目置于数字选择器小部件内的中心 的相关文章

随机推荐