> 技术文档 > 原生html+js+jq+less 实现时间区间下拉弹窗选择器

原生html+js+jq+less 实现时间区间下拉弹窗选择器

 

html弹窗

 
选择时间
<!-- 2025-7-28 --> 开始时间结束时间
2025年
2024年
2023年
2022年
2021年
2020年
1月
2月
3月
4月
5月
6月
7月
8月
9月
10月
11月
12月
1日
2日
3日
4日
5日
6日
7日
8日
9日
10日
11日
12日
13日
14日
15日
16日
17日
18日
19日
20日
21日
22日
23日
24日
25日
26日
27日
28日
29日
30日

 less样式

.popupForm { display: none; width: 100%; height: 100%; position: fixed; bottom: 0; left: 0; background-color: #57575748; .pop-box { position: absolute; bottom: 0; left: 0; height: auto; width: 100%; border-radius: 0.625rem 0.625rem 0rem 0rem; background: #ffffff; padding: 1.25rem 0; } // 取消 .cancel { font-size: 0.75rem; color: #606266; position: absolute; top: 1rem; right: 1.375rem; } .title { font-size: 1rem; color: #3d3d3d; text-align: center; } // 时间选择器 .time-box { padding: 0.625rem 0; .time { font-size: 1rem; color: #606266; text-align: center; span { margin: 0 1.6875rem; padding: 0.1875rem 0.625rem; border-bottom: 0.0625rem solid #d8d8d8; font-size: 0.875rem; color: #909399; } .active { color: #1890ff; } } .time-list { height: 12.5rem; margin: 1.875rem 0; position: relative; box-shadow: inset 0 0.3125rem 0.625rem #d5d5d52e, inset 0 -0.3125rem 0.625rem #d5d5d52e; &::after { content: \"\"; position: absolute; top: 5rem; left: 0; width: 100%; height: 0.0625rem; background-color: #eaeaea; } &::before { content: \"\"; position: absolute; bottom: 5rem; left: 0; width: 100%; height: 0.0625rem; background-color: #eaeaea; } & > div { flex: 1; text-align: center; overflow-y: auto; &::-webkit-scrollbar { width: 0; height: 0; } .li { height: 2.5rem; font-size: 0.875rem; color: #606266; padding: 0.625rem 0; } } } .bottom { gap: 2.5rem; .reset { width: 7.875rem; height: 1.6875rem; border-radius: 2.125rem; border: 0.0625rem solid #c4302c; font-size: 0.875rem; color: #c4302c; } .confirm { width: 7.875rem; height: 1.6875rem; border-radius: 2.1875rem; background: linear-gradient(180deg, #eb140f 0%, #c70504 100%); font-size: 0.875rem; color: #ffffff; } } }}

js整体逻辑 

$(() => { // 当前年份 const thisYear = new Date().getFullYear(); const ITEM_HEIGHT = 40; // 每个选项高度 // 滚动类型:0=开始时间,1=结束时间 let type = 0; let startTime = \"\"; //开始时间 let endTime = \"\"; //结束时间 // 存储滚动下标 const scrollValues = { startYear: 0, startMonth: 1, startDay: 1, endYear: 0, endMonth: 1, endDay: 1, }; // 缓存 DOM 元素 const $year = $(\".time-list .year\"); const $month = $(\".time-list .month\"); const $day = $(\".time-list .day\"); const $timeSpans = $(\".time-box .time span\"); // ========== 生成年份列表(100年)========== function renderYearList() { let html = \'
\'; for (let i = 0; i < 100; i++) { html += `
${thisYear - i}年
`; } html += \'
\'; $year.html(html); } // ========== 生成月份列表(1~12月)========== function renderMonthList() { let html = \'
\'; for (let i = 1; i <= 12; i++) { html += `
${i}月
`; } html += \'
\'; $month.html(html); } // ========== 获取某年某月的天数(month: 1~12)========== function getDaysInMonth(year, month) { return new Date(year, month, 0).getDate(); } // ========== 更新日列表(根据当前年月动态生成)========== function updateDayList() { const yearOffset = type === 0 ? scrollValues.startYear : scrollValues.endYear; const month = type === 0 ? scrollValues.startMonth : scrollValues.endMonth; const year = thisYear - yearOffset; const days = getDaysInMonth(year, month); const dayKey = type === 0 ? \"startDay\" : \"endDay\"; const currentDay = scrollValues[dayKey]; // 如果当前日超出该月最大天数,修正为最后一天 if (currentDay > days) { scrollValues[dayKey] = days; } // 生成日 HTML let html = \'
\'; for (let i = 1; i <= days; i++) { html += `
${i}日
`; } html += \'
\'; $day.html(html); // 滚动到当前日 $day.scrollTop((scrollValues[dayKey] - 1) * ITEM_HEIGHT); } // ========== 格式化为 YYYY-MM-DD 字符串 ========== function formatTime(yearOffset, month, day) { const y = thisYear - yearOffset; const m = month < 10 ? `0${month}` : month; const d = day { let isAnimating = false; $container.on(\"wheel\", function (e) { e.preventDefault(); if (isAnimating) return; const delta = e.originalEvent.deltaY > 0 ? 1 : -1; const current = $container.scrollTop(); const maxScroll = this.scrollHeight - this.clientHeight; const nextScroll = Math.max( 0, Math.min(maxScroll, current + delta * ITEM_HEIGHT) ); isAnimating = true; $container.animate({ scrollTop: nextScroll }, 200, () => { isAnimating = false; }); // 计算滚动索引 const index = Math.round(nextScroll / ITEM_HEIGHT); // 更新对应值 if ($container.is($year)) { scrollValues[`${type === 0 ? \"start\" : \"end\"}Year`] = index; } else if ($container.is($month)) { scrollValues[`${type === 0 ? \"start\" : \"end\"}Month`] = index + 1; } else if ($container.is($day)) { scrollValues[`${type === 0 ? \"start\" : \"end\"}Day`] = index + 1; } updateDisplay(); // 更新显示 updateDayList(); // 重新生成日(月或年变化时) }); }); } // ========== 切换时间类型(点击“开始/结束”)========== $timeSpans.parent().on(\"click\", \"span\", function () { type = $(this).index(); const values = [ scrollValues[`${type === 0 ? \"start\" : \"end\"}Year`], scrollValues[`${type === 0 ? \"start\" : \"end\"}Month`] - 1, scrollValues[`${type === 0 ? \"start\" : \"end\"}Day`] - 1, ]; $year.scrollTop(values[0] * ITEM_HEIGHT); $month.scrollTop(values[1] * ITEM_HEIGHT); $day.scrollTop(values[2] * ITEM_HEIGHT); }); // ========== 初始化 ========== $(function () { renderYearList(); renderMonthList(); updateDayList(); // 初始生成日 initWheel(); // 默认显示当前日期(可选) // $timeSpans.eq(0).text(formatTime(0, 1, 1)); // $timeSpans.eq(1).text(formatTime(0, 1, 1)); }); // ========== 确认时间 ========== window.confirmTime = function () { // 判断开始结束时间是否正确 console.log(startTime, endTime); if (startTime && endTime && startTime > endTime) { // message.error(\"结束时间不能小于开始时间\"); } else if (!startTime && endTime) { // message.error(\"请选择开始时间\"); } else if (startTime && !endTime) { // message.error(\"请选择结束时间\"); } else { // 关闭弹窗 请求接口 toggleForm(10); } }; // ========== 重置时间 ========== window.resetTime = function () { $(\".time-box .time\").html(\"开始时间结束时间\"); Object.assign(scrollValues, { startYear: 0, startMonth: 1, startDay: 1, endYear: 0, endMonth: 1, endDay: 1, }); $(\".time-box .time span\").eq(0).click(); // 触发切换并滚动 };});

打开关闭弹窗 

function toggleForm(type) { // console.log(type); $(`#popupForm${type}`).fadeToggle(200);}

 

华南自动化展