1. 程式人生 > >原生JS實現移動端模組的左右滑動切換效果,基於vue、stylus

原生JS實現移動端模組的左右滑動切換效果,基於vue、stylus

原生JS實現移動端模組的左右滑動動畫效果,基於vue、stylus

大概實現方案:

手指touch螢幕的整個過程,會派發touchstart、touchmove、touchend三個事件,對這三個事件設定相應函式,通過移動過程中位置的變化計算出偏移值,進行對應的設定。

注:以下講解請忽略資料(可用兩個設定高度寬度的空dom代替),這篇部落格只針對切換效果的實現

效果展示

①歌詞未左滑:


②歌詞左滑後:


所需資料定義:


解釋:currentShow用於標記當前顯示的模組為CD模組還是歌詞模組、touchInfo物件用於儲存touch事件的相關屬性

vue dom結構:


stylus:


原生JavaScript:

解釋:三個皆為相應dom中touch事件的方法,詳情請註釋即可。

     middleTouchStart(e) {
        // touch開始時,將touchInfo物件設定為已初始化狀態
        this.touchInfo.initiated = true
        // 用來判斷是否是一次移動
        this.touchInfo.moved = false
        const touch = e.touches[0]
        // 記錄touch位置的橫座標與縱座標
        this.touchInfo.startX = touch.pageX
        this.touchInfo.startY = touch.pageY
      },
      middleTouchMove(e) {
        if (!this.touchInfo.initiated) {
          return
        }
        const touch = e.touches[0]
        // 橫座標與縱座標的偏移
        const deltaX = touch.pageX - this.touchInfo.startX
        const deltaY = touch.pageY - this.touchInfo.startY
        if (Math.abs(deltaY) > Math.abs(deltaX)) {
          return
        }
        if (!this.touchInfo.moved) {
          this.touchInfo.moved = true
        }
        // 判斷當前顯示的是cd還是歌詞,如果是cd,則當前左偏移值為0,否則偏移值為-window.innerWidth
        const left = this.currentShow === 'cd' ? 0 : -window.innerWidth
        // 求偏移值
        const offsetWidth = Math.min(0, Math.max(-window.innerWidth, left + deltaX))
        // 求偏移值佔可視區域的百分比,用於判斷是否應該切換顯示狀態
        this.touchInfo.percent = Math.abs(offsetWidth / window.innerWidth)
        // 移動時歌詞模組的偏移效果
        this.$refs.lyricList.$el.style.transform = `translate3d(${offsetWidth}px,0,0)`
        this.$refs.lyricList.$el.style.transitionDuration = 0
        // 移動時CD模組的淡出效果
        this.$refs.cd.style.opacity = 1 - this.touchInfo.percent
        this.$refs.cd.style.transitionDuration = 0
      },
      middleTouchEnd() {
        if (!this.touchInfo.moved) {
          return
        }
        let offsetWidth
        let opacity
        if (this.currentShow === 'cd') {
          // 移動百分比大於螢幕一半,則切換顯示狀態
          if (this.touchInfo.percent > 0.5) {
            offsetWidth = -window.innerWidth
            opacity = 0
            this.currentShow = 'lyric'
          } else {
            offsetWidth = 0
            opacity = 1
          }
        } else {
          if (this.touchInfo.percent < 0.5) {
            offsetWidth = 0
            this.currentShow = 'cd'
            opacity = 1
          } else {
            offsetWidth = -window.innerWidth
            opacity = 0
          }
        }
        // 最終狀態的設定
        // 動畫時間
        const time = 300
        // touch完畢後歌詞模組應該放置的位置
        this.$refs.lyricList.$el.style.transform = `translate3d(${offsetWidth}px,0,0)`
        this.$refs.lyricList.$el.style.transitionDuration = `${time}ms`
        // touch完畢後CD模組的透明度
        this.$refs.cd.style.opacity = opacity
        this.$refs.cd.style.transitionDuration = `${time}ms`
        // 一次touch完成後,重置touchInfo物件尚未初始化狀態
        this.touchInfo.initiated = false
      }

至此,原生JS實現移動端模組的左右滑動動畫效果實現完成。