仿一個好玩的滑動效果
阿新 • • 發佈:2018-09-17
tde 滑動效果 wce else 技術 cto rev opacity art
起因
昨天跑步的時候,看到一個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
。(完)
仿一個好玩的滑動效果