在 JavaScript 中的数字选择器小部件中居中选定的项目
Center Selected Item Inside a Number Picker Widget in JavaScript
[前提条件]
我很难弄清楚如何使 数字选择器小部件 的行为类似于 mobile picker component。如果用户默认分配了一个数字,那么selected
这个数字应该会在页面加载时自动对齐到中心。
[问题]
- 如何默认将此元素
<div class="cell selected">10</div>
对齐到 scrollport 的中心?
- 不要依赖任何插件。
"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>
[期待结果]
您可以尝试设置父项的滚动位置,方法是用 scrollHeight
减去所选值的 offsetTop
以获得精确的垂直居中位置:
"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>
[前提条件]
我很难弄清楚如何使 数字选择器小部件 的行为类似于 mobile picker component。如果用户默认分配了一个数字,那么selected
这个数字应该会在页面加载时自动对齐到中心。
[问题]
- 如何默认将此元素
<div class="cell selected">10</div>
对齐到 scrollport 的中心? - 不要依赖任何插件。
"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>
[期待结果]
您可以尝试设置父项的滚动位置,方法是用 scrollHeight
减去所选值的 offsetTop
以获得精确的垂直居中位置:
"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>