资讯专栏INFORMATION COLUMN

干货--手把手撸vue移动UI框架:滑动轮播

MSchumi / 2273人阅读

摘要:其次父组件中负责通用的功能,以及轮播的整体架构,其结构如下。下面的是一种移动端的适配方案。接下来实现函数运用动画切换到指定下标的子项到此为止,咱们就已经完成了一个初步的滑动切换轮播图的功能了。

前言

昨天写了一篇侧边菜单组件的文章,阅读人数挺多的,内心很欣喜(偷着乐,第一篇文章有这么多人看)!乘着这股劲,今天在继续写一篇我们平时工作中更常用的滑动轮播组件的文章。

效果展示

老规矩,咱们先看做成后的效果,然后咱们再一步步的开始制作:

组件组成分析

在实际的工作中,咱们轮播中的内容形式可能有很多种:图片、文本、视频、其他DOM结构等。所以咱们的轮播组件必须能满足这几种应用情况。那么我们可以把组件分两部分:

可以高度定制的子组件,负责渲染轮播中的每一个子项

负责轮播的父组件,用来处理通用的滑动事件、自动轮播、指示器等功能

我们现在这定义子组件的名称为swiper-item;父组件名称为swiper

DOM组成

首先咱们的子组件中负责渲染自定义的内容,则子组件中需要一个插槽slot。

swiper-item:

其次父组件中负责通用的功能,以及轮播的整体架构,其DOM结构如下。

swiper:

默认插槽在使用的时候渲染咱们轮播的子项,通常为swiper-item;indicator插槽用来自定义指示器的样式,因为在实际使用过程中指示器样式很可能是需要定制的。

css样式

移动端的视图大小有限,子项的大小一般是父组件的全部可视视图。
swiper-item:

下面的vw是一种移动端的适配方案(https://www.w3cplus.com/css/t...)。其他的适配方案还有淘宝的flexible,这个css大家根据自己的适配方案更改下,这里不做过多描述,大家感兴趣的自行百度。
swiper:

javascript

老规矩,写JS代码前咱们先理清交互逻辑:

页面渲染开始,首先把所有子组件挂载到DOM上,当所有子节点挂载好了后初始化父组件

同理,当轮播组件销毁的时候先销毁子组件,再销毁父组件

初始化的时候需要:

获取父组件容器DOM节点、以及父组件节点的宽度

获取到所有子组件节点

给所有子节点依次设置好初始坐标

给父节点绑定touch事件

初始化完成后,当手指触摸到屏幕瞬间,记录当前手指起始的坐标

当手指移动的过程中,阻止页面中的默认事件,根据当前坐标以及起始坐标计算手指X、Y轴移动的距离

如果X轴移动比Y轴多则判断手指在横向移动,否则为竖向移动

如果横向移动则移动子项中的位置,修改所有子项的坐标

手指离开屏幕的时候判断手指移动总距离,如果大于一个临界值则轮播切换到下一屏或者上一屏(根据滑动方向判定),否则重置会原始状态

swiper-item:

export default {
  mounted () {
    this.$nextTick(() => {
      this.$parent.init()
    })
  },
  beforeDestroy () {
    this.$nextTick(() => {
      this.$parent.destroy()
    })
  }
}

swiper:



初始化完成后,咱们接下来编写咱们的moveStart、moving、moveEnd三个touch事件,在methods中完善这三个函数,并添加一个临界值sensitivity以及一个阻力系数,阻力系数有啥用,注意看下面代码的注释:

data () {
  return {
    sensitivity: 60,
    resistance: 0.3
  }
},
methods: {
  moveStart (e) {
    this.start.x = e.changedTouches[0].pageX
    this.start.y = e.changedTouches[0].pageY
    this.setTransition("none")
  },
  moving (e) {
    e.preventDefault()
    e.stopPropagation()
    let distanceX = e.changedTouches[0].pageX - this.start.x
    let distanceY = e.changedTouches[0].pageY - this.start.y
    if (Math.abs(distanceX) > Math.abs(distanceY)) {
      this.isMoving = true
      this.move.x = this.start.x + distanceX
      this.move.y = this.start.y + distanceY
      // 当活动子项为第一项且手指向右滑动或者活动项为最后一项切向左滑动的时候,添加阻力,形成一个拉弹簧的效果
      if ((this.active === 0 && distanceX > 0) || (this.active === (this.items.length - 1) && distanceX < 0)) {
        distanceX = distanceX * this.resistance
      }
      this.setTransform(distanceX)
    }
  },
  moveEnd (e) {
    if (this.isMoving) {
      e.preventDefault()
      e.stopPropagation()
      let distance = this.move.x - this.start.x
      if (Math.abs(distance) > this.sensitivity) {
        if (distance < 0) {
          this.next()
        } else {
          this.prev()
        }
      } else {
        this.back()
      }
      this.reset()
      this.isMoving = false
    }
  },
  // 切换下一屏
  next () {},
  // 切换下一屏
  prev () {},
  // 如果滑动达不到阈值,所有元素重置回之前状态
  back () {},
  // 重置动画中用到的一些变量
  reset () {},
  destroy () {
    this.setTransition("none")
  }
}

接下来咱们完善下next、prev、back、reset函数:

next () {
  let index = this.active + 1
  // 运用动画切换到指定下标的子项
  this.go(index)
},
prev () {
  let index = this.active - 1
  // 运用动画切换到指定下标的子项
  this.go(index)
},
reset () {
  this.start.x = 0
  this.start.y = 0
  this.move.x = 0
  this.move.y = 0
},
back () {
  this.setTransition()
  this.setTransform()
},
go (index) {}

go函数用来做轮播切换的效果。我们在写代码的过程中,可以先定义一个函数来做某个事情,然后再后面用代码来实现逻辑,这样的咱们写代码过程中的思路就会很清晰。接下来实现go函数:

// 运用动画切换到指定下标的子项
go (index) {
  this.active = index
  if (this.active < 0) {
    this.active = 0
  } else if (this.active > this.items.length - 1) {
    this.active = this.items.length - 1
  }
  this.$emit("change", this.active)
  this.setTransition()
  this.setTransform()
}

到此为止,咱们就已经完成了一个初步的滑动切换轮播图的功能了。但是很多时候,我们的轮播是需要自动播放的,那么如何在现在的基础上增加自动轮播呢?请大家自己思考下,哈哈。下面我们把当前代码整合下:





写在最后

今天写这篇文章的时候发现有两个兄弟给我微信转了钱,很谢谢这两个兄弟,感谢你们的支持。其实说实话,我花心思写这个主要目的不是为了钱,而是兴趣,否则我用这个时间用来做点私活什么的收入比这个多多了。只是看到大家的支持,内心很有成就感,尽管很多时候只有1分钱,所以也希望大家有钱的捧个钱场,没钱的捧个人场,哈哈。(未完待续...)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93270.html

相关文章

  • 干货--把手vue移动UI框架:侧边菜单

    摘要:最后提醒下,代码中使用而非的原因是为了启动移动端手机的动画加速,提升动画流畅度。 前言 最近面试发现很多前端程序员都从来没有写过插件的经验,基本上都是网上百度。所以打算写一系列文章,手把手的教一些没有写过组件的兄弟们如何去写插件。本系列文章都基于VUE,核心内容都一样,会了之后大家可以快速的改写成react、angular或者是小程序等组件。这篇文章是第一篇,写的是一个类似QQ的侧边菜...

    bergwhite 评论0 收藏0
  • 干货--把手vue移动UI框架动加载

    摘要:前言在我们移动端还有一个很常用的组件,那就是滑动加载更多组件。平常我们看到的很多插件实现相当复杂就觉得这个组件很难,其实不是的这个组件其实可以很简单的就实现出来,而且体验也能非常的棒当然我们没有实现下拉刷新功能下面我们就一起来实现这个组件。 前言 在我们移动端还有一个很常用的组件,那就是滑动加载更多组件。平常我们看到的很多插件实现相当复杂就觉得这个组件很难,其实不是的!!这个组件其实可...

    Harpsichord1207 评论0 收藏0

发表评论

0条评论

MSchumi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<