原生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实现移动端模块的左右滑动动画效果实现完成。

Logo

前往低代码交流专区

更多推荐