实现逻辑
export default {
name: "",
mounted() {
document.addEventListener("wheel", this.onWheel, { passive: false })
},
beforeDestroy() {
document.removeEventListener("wheel", this.onWheel)
},
methods: {
onWheel(e) {
const { target, wheelDelta } = e
// 判断一下鼠标所处元素是否为时间选择器
if (target.className.includes("el-time-spinner")) {
// 获取正确的目标元素
const ele = this.getCorrectTarget(target)
if (ele) {
// 获取原始的滚动距离
const originScrollTop = ele.scrollTop
// 获取 ele 的高度
const eleHeight = ele.scrollHeight
// 判断一下,是否需要继续计算
if (originScrollTop === eleHeight) return
// 使用人为滚动距离,每次滚动 ±8px,单个时间的 div 高度为 32px,值越小越能精准控制滚动
const rollingDistance = 8
// 判断滚动方向
if (wheelDelta > 0) {
// 向上滚动
const scrollTop = originScrollTop - rollingDistance
ele.scrollTop = scrollTop < 0 ? 0 : scrollTop
} else {
// 向下滚动
const scrollTop = originScrollTop + rollingDistance
ele.scrollTop = scrollTop > eleHeight ? eleHeight : scrollTop
}
// 阻止鼠标滚动
e.preventDefault()
}
}
},
getCorrectTarget(target) {
// case 的判断是写死的,因为 el-date-picker 的类名不会变
// 如果人为改变了 el-date-picker 的类名,需要修改一下 case 的判断
const { className, parentElement } = target
switch (className) {
case "el-scrollbar__view el-time-spinner__list":
return parentElement
case "el-time-spinner__item active":
case "el-time-spinner__item":
return parentElement.parentElement
}
}
}
}
拓展阅读
1. 一开始选择 scroll-snap-type 这个 css 属性来实现吸附滚动,但只能吸附,不能精准控制滚动距离。在首页等大高度页面下比较好用,而在高度比较小的 div 上,鼠标滚动一次后,会连续滚动多个 div,就像这个时间选择器,带给用户不好的体验
2. 所以,只能选择使用监听鼠标滚动的事件 wheel 来实现,div 的精准滚动
3. 同理,如果使用的是别的 UI 框架,稍微修改即可实现精准滚动的效果
4. 相比于需要关注才能查看文章的博主,我是否小胜一筹?留个小赞吧~