起因
昨天跑步的时候,看到一个app(华为手机自带的运动健康)上的滑动效果很有意思,回来之后就想着,能不能在dom上实现一下,于是有了这篇文章。首先看一下效果图,滑动下面的绿色滑块可以看到效果:
贴出app上的效果图,模仿效果可以说是差强人意吧:
实现
其实原理很简单,就是在小圆点移动时,计算数字和小圆点的距离,来控制数字的上升和下降。
首先,要使小圆点跟随鼠标移动起来:代码如下:
slide.addEventListener(‘mousedown‘, function(e){
e.preventDefault()
let left = parseInt(slide.style.left) || 0
let startX = e.clientX
// slider能移动的最远距离
let maxLength = document.querySelector(‘.table‘).getBoundingClientRect().width - slideWidth
function move(e){
// move的逻辑
}
document.addEventListener(‘mousemove‘, move)
document.addEventListener(‘mouseup‘, function(){
document.removeEventListener(‘mousemove‘, move)
})
})
这段代码监听了3个事件,mousedown
,mouseup
,mousemove
,当鼠标按下时,触发滑块的mousedown事件,同时给document绑定了mousemove和mouseup事件,来使滑块可以跟着鼠标移动,当鼠标弹起时,使滑块不再随鼠标移动。
之所以在document元素上监听mousemove事件,是因为如果在滑块上监听,很容易由于鼠标滑动过快,造成鼠标离开滑块的区域,导致mousemove事件失效,而在document元素上监听就不会有这样的问题。接下来我们来看看move
这个函数:
function move(e){
e.preventDefault()
let moveX = e.clientX - startX
if(left + moveX < 0 || left + moveX > maxLength) {
return
}
newLeft = left + moveX
let newCenterLeft = newLeft + slideWidth / 2
slide.style.left = newLeft + ‘px‘
// 控制数字的上升和下降
// console.log(‘========‘)
for(let label of labels){
let dist = label.left - newCenterLeft
// console.log(dist, slideWidth/2)
if(Math.abs(dist) <= slideWidth / 2){
label.el.style.top = Math.abs(dist) - slideWidth / 2 + ‘px‘
label.el.style.opacity = 0.3 + Math.abs(1 - dist / (slideWidth / 2)) * 0.7
} else {
label.el.style.top = ‘0px‘
label.el.style.opacity = 0.3
}
}
}
move函数主要干了两件事,一个是改变滑块的位置,另一个是通过实时判断数字和滑块的距离来改变数字的高度。改变位置都是通过改变元素的left/top样式来实现的。在改变数字高度的实现上,偷了一点懒,从形状上看,滑块边缘是一个半圆形,因此数字距离底部的高度(y)和数字距离滑块圆心的距离(x)应该是一个非线性的关系,函数表达式:
y = Math.sqrt(R*R - x*x)// R是滑块边缘半径
在实现上直接线性转换了一下R-x
。(完)
原文地址:https://www.cnblogs.com/imgss/p/9655845.html
时间: 2024-11-05 21:49:35