【问题标题】:Touchend iOS won't fired if leaving screen slowly如果缓慢离开屏幕,Touchend iOS 不会触发
【发布时间】:2016-02-22 11:03:09
【问题描述】:

我构建了一个处理 touchstarttouchendtouchmove 事件的滑块。

它在 Android 和 iOS 上运行良好。 只有当我将 iOS 上的手指慢慢移出屏幕时,touchend 事件才会触发。 在我将手指放回屏幕后,touchend 事件立即触发,但不是触摸开始。

有人知道为什么 touchend 事件不会触发吗?

我搜索了几个小时才找到解决方案。 我试过touchcancel,但没有帮助。

Javascript:

this.element = document.createElement('div');
this.element.classList.add('slider');
parent.appendChild(this.element);
//other stuff

this.element.addEventListener('touchstart', ()=> {
    console.log('start');
});
this.element.addEventListener('touchend', ()=> {
    console.log('end');
});
this.element.addEventListener('touchmove', ()=> {
    console.log('move');
});

css:

.slider{
      display: block;
      position: relative;
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
}

编辑#1

我也试过gestureend,但没有帮助。

我发现只有当我使用主页按钮滑动到一侧时它才不会触发(我处于横向模式)。

【问题讨论】:

    标签: javascript ios touch dom-events


    【解决方案1】:

    我在使用 Cordova 封装的 Vue.js 应用程序中构建滑块时遇到了完全相同的问题。

    我没有找到导致 touchend 事件不会在 ios 设备的“按钮端”触发的这种行为的原因,但我确实创建了一个解决方法。

    我假设这与您不再相关,但它可能会帮助遇到此问题的其他人:

    我的事件上下文(对于非 Vue 用户 this.$refs.profileSlider 只是对包裹我的滑块的元素的 DOM 引用):

      this.$refs.profileSlider.addEventListener('mousedown', this.lock, false);
      this.$refs.profileSlider.addEventListener('touchstart', this.lock, false);
    
      this.$refs.profileSlider.addEventListener('mousemove', this.drag, false);
      this.$refs.profileSlider.addEventListener('touchmove', this.drag, false);
    
      this.$refs.profileSlider.addEventListener('mouseup', this.move, false);
      this.$refs.profileSlider.addEventListener('touchend', this.move, false);
    

    为了确保move() 函数即使在touchend 事件没有触发(当用户从​​屏幕末端滑出时)也被调用,我在touchmove 末尾添加了一个条件检查处理程序,这里称为drag

      // Rest of touchmove handler here
      const unified = this.unify(e);
    
      if (unified.clientX >= window.innerWidth - 3 || unified.clientX <= 3) {
        this.$refs.profileSlider.dispatchEvent(new TouchEvent('touchend', e));
      }
    

    此函数中的etouchmove 事件的上下文。这样drag() 处理程序将正常运行,然后检查touchmove 事件是否发生在屏幕任一侧的3px 内(此灵敏度适用于我的目的)。如果是这样,它会触发一个新的 touchend TouchEvent 并传递与之前的 touchmove 相同的 e 值。

    这解决了当用户继续触摸屏幕边缘时touchend 不触发的问题。相反,touchend 被抢先触发,就在滑动退出屏幕之前。

    // 作为参考,上述代码块中调用的unify 函数仅检查事件中的changedTouches,如果存在则返回第一个changedTouch

    unify(e) {
      return e.changedTouches ? e.changedTouches[0] : e;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-05-28
      • 1970-01-01
      • 2013-04-18
      • 2020-12-11
      • 1970-01-01
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多