You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求Angular Material风格、类似Mobiscroll演示的滚动数字选择组件方案

嘿,我完全get到你的需求了——你想要的不是那个时间选择器功能,而是它那种上下滚动选择数字/选项的交互效果对吧?这种组件有个通用的名字叫滚轮选择器(Wheel Picker),也有人叫它滚动选择器、滚筒选择器,先给你几个实用的方向:

一、现成的类库推荐(直接用,不用自己造轮子)

其实很多UI组件库都自带这种滚轮选择器,而且支持自定义选项内容,不一定局限于时间:

  • Mobiscroll:你看的演示本身就是它的产品,它的wheel组件可以单独使用,完全可以自定义滚动的选项列表(比如数字、自定义文本),去查它的官方文档里的独立滚轮组件部分就行。
  • Ionic Picker:如果你在用Ionic框架,它的ion-picker组件原生支持这种滚动选择,配置选项非常灵活。
  • Vanilla JS Wheel Picker:纯原生JS实现的轻量滚轮选择器,没有框架依赖,适合不需要复杂功能的场景。
  • React Native Picker(如果是移动端React项目):React生态里专门做滚动选择的组件,适配移动端触摸交互。

这些类库都帮你处理好了触摸拖拽、自动吸附、滚动动画这些细节,直接配置选项就能用。

二、自己动手实现的核心思路

如果想自己编码实现,核心是处理容器裁剪、滚动位移、触摸/滚轮交互这几个点,步骤大概是:

  1. 结构与样式:
    • 用一个固定高度的容器,设置overflow: hidden,只显示中间区域的选项。
    • 内部的选项列表用绝对定位,每个选项高度固定,让中间位置的选项高亮(比如加粗、变色)。
    • 可以给容器加个中间的分隔线,让用户清楚哪个是选中项。
  2. 交互逻辑:
    • 触摸拖拽:监听touchstart记录初始位置,touchmove时计算拖拽距离,实时更新选项列表的transform: translateY()值。
    • 自动吸附:拖拽结束后,计算当前位置距离最近的选项的偏移量,用过渡动画把列表滚动到对齐的位置,避免半选状态。
    • 桌面端滚轮:监听wheel事件,每次滚动调整一个选项的高度位移,同样做吸附处理。
  3. 核心计算:要提前算好每个选项的高度,滚动时的位移必须是选项高度的整数倍,这样才能保证选中项始终对齐中间位置。

给你一个极简的代码示例(纯HTML/CSS/JS),能帮你理解基础逻辑:

<div class="wheel-picker">
  <div class="wheel-container">
    <div class="wheel-item">0</div>
    <div class="wheel-item">1</div>
    <div class="wheel-item">2</div>
    <div class="wheel-item">3</div>
    <div class="wheel-item">4</div>
    <div class="wheel-item">5</div>
    <div class="wheel-item">6</div>
    <div class="wheel-item">7</div>
    <div class="wheel-item">8</div>
    <div class="wheel-item">9</div>
  </div>
</div>
.wheel-picker {
  width: 120px;
  height: 180px;
  overflow: hidden;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  position: relative;
  margin: 20px;
}

.wheel-container {
  position: absolute;
  top: 60px; /* 初始让第2个选项(索引1)在中间 */
  transition: transform 0.2s ease-out;
  width: 100%;
}

.wheel-item {
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  color: #666;
}

.wheel-item.active {
  color: #1976d2;
  font-weight: bold;
}

/* 中间选中线 */
.wheel-picker::after {
  content: "";
  position: absolute;
  top: 60px;
  left: 0;
  right: 0;
  height: 60px;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
  pointer-events: none;
}
const picker = document.querySelector('.wheel-picker');
const container = document.querySelector('.wheel-container');
const items = document.querySelectorAll('.wheel-item');
const itemHeight = 60; // 每个选项的高度
let startY = 0;
let currentY = 0;
let isDragging = false;

// 初始化激活项
updateActiveItem();

// 触摸开始
picker.addEventListener('touchstart', (e) => {
  isDragging = true;
  startY = e.touches[0].clientY - currentY;
  container.style.transition = 'none'; // 拖拽时关闭过渡
});

// 触摸移动
picker.addEventListener('touchmove', (e) => {
  if (!isDragging) return;
  currentY = e.touches[0].clientY - startY;
  container.style.transform = `translateY(${currentY}px)`;
});

// 触摸结束
picker.addEventListener('touchend', () => {
  isDragging = false;
  // 计算应该吸附到哪个选项
  const closestIndex = Math.round(-currentY / itemHeight);
  const clampedIndex = Math.max(0, Math.min(closestIndex, items.length - 1));
  currentY = -clampedIndex * itemHeight;
  container.style.transition = 'transform 0.2s ease-out';
  container.style.transform = `translateY(${currentY}px)`;
  updateActiveItem();
});

// 更新激活项样式
function updateActiveItem() {
  const activeIndex = Math.round(-currentY / itemHeight);
  items.forEach((item, index) => {
    item.classList.toggle('active', index === activeIndex);
  });
}

这个示例实现了最基础的触摸滚动和自动吸附功能,你可以在此基础上扩展更多功能(比如循环滚动、自定义选项内容、滚轮支持等)。

内容的提问来源于stack exchange,提问作者lemek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:03:56