1. 程式人生 > >仿一個好玩的滑動效果

仿一個好玩的滑動效果

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。(完)

仿一個好玩的滑動效果