Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

从一个左滑删除组件到touch系列事件的思考 #2

Open
SoloJiang opened this issue Jun 18, 2019 · 0 comments
Open

从一个左滑删除组件到touch系列事件的思考 #2

SoloJiang opened this issue Jun 18, 2019 · 0 comments
Labels

Comments

@SoloJiang
Copy link
Owner

左滑删除是目前很多应用都必不可少的功能,像QQ,微信都有使用这种方式,并且在此基础上有拓展的交互设计。

需求在哪?

我们青柚工作室的一个正在开发的小程序项目中,UI哥哥设计了一个左滑的组件,想让用户通过左滑来取消对这个Item的关注。

怎么去做 ?

我一开始觉得在小程序中不存在 dom 结构不是很方便完成这个效果,后来在京东商城小程序中发现了这个类似的实现,于是开始思考如何去完成这个看似很简单的需求。

通过观察发现其实就是最普通的touchstart touchend事件就行了,于是我几分钟就写出了下面这段代码:

touchStart(e) {
  this.touchStartClientX = e.touches[0] ? e.touches[0].clientX : 0
    },
touchEnd(e) {
  this.touchEndClientX = e.touches[0] ? e.touches[0].clientX : 0
  const offsetX = Number(this.touchStartClientX) - Number(this.touchEndClientX)
  if (offsetX > 30) {
    this.$_slideFlex = this.slideFlex
  } else if (-offsetX > 30) {
    this.$_slideFlex = 0
  }
}

在没打开控制台前,嗯,很美好,效果实现了,可以收拾东西回家了。

但是当我打开控制之后,"Oh! WTF! What's this ?"

报错是什么?

当我手指离开的那一刹那,可控制台红红的字告诉我 e.touches[0] is undefined,怎么会呢,按照我的认知,在发生触摸的时候会产生一个touch对象,触摸事件中的touches数组用来记录当前触摸操作产生的touch对象,注意: 一个触摸点只会产生一个touch对象,所以就算是touchmove事件发生,每一次move都会新建一个触摸点,从而touches的数组长度依然为1。

原因

问题来了,既然touches的长度为1,那么为什么我touchend的时候会报错呢,经过一番查询,找了原因:touchend事件发生的时候意味着触摸事件结束,事件触发的时刻,touch对象已经被销毁掉了,所以touches数组的长度为0。

解决方案

在touchend事件中获取触摸点位置的属性不使用touches[0],而使用changedTouches[0]来获取,这个属性是用来记录上次触摸改变的touch对象,所以这个值就是用户在结束触摸操作之前产生的最后一个触摸对象,通过它就可以获取到坐标。

结论

与touchend事件中touches[0]是undefined类似的是,touchstart事件中changedTouches[0]也是undefined,因为触摸开始的瞬间是不存在上一个触摸点的。

关键 以上的结论完全是基于单指触摸的,如果是多指触摸就存在不成立的情况,就需要借助手势操作的事件一起来分析用户行为了。

最后的代码:

touchStart(e) {
  this.touchStartClientX = e.touches[0] ? e.touches[0].clientX : 0
    },
touchEnd(e) {
  this.touchEndClientX = e.changedTouches[0] ? e.changedTouches[0].clientX : 0
  const offsetX = Number(this.touchStartClientX) - Number(this.touchEndClientX)
  if (offsetX > 30) {
    this.$_slideFlex = this.slideFlex
  } else if (-offsetX > 30) {
    this.$_slideFlex = 0
  }
}

最后的最后推一下我写的 wepy-slide-card,还在不断改进中,但是这个组件的目的只是为了滑块的交互,不会将其演变成比较重的swiper组件,使用方法:

npm install wepy-slide-card --save

orz。。卒。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant