首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从javascript中的触摸事件中排除滚动

从javascript中的触摸事件中排除滚动
EN

Stack Overflow用户
提问于 2018-09-21 01:50:22
回答 1查看 742关注 0票数 0

我正在尝试用javascript创建一个swipeout列表,就像android上的Gmail应用程序一样。我使用的事件包括touchstarttouchmovetouchend。当我向左或向右滑动列表项时,一切正常,但当我试图在列表中向下滚动时,它会移动我的手指所在的列表项(因为当我滚动时,我的手指不会完全垂直)。有没有一种简单的方法来解决这个问题,通过区分swipe事件和scroll事件或类似的事件?

代码语言:javascript
复制
const SwipeOutList = function(listId, items) {
  const listElement = document.getElementById(listId);
  let touchStart = null;
  let movedTo = null;

  const findContentParent = function(element) {
    if(!element.parentNode) {
      return null;
    }
    if(element.className === 'content') {
      return element;
    } else {
      return findContentParent(element.parentNode);
    }
  };

  const fja = function(e) {
    movedTo = e.changedTouches[0].clientX;
    let contentElement;

    if(e.target.className === 'content') {
      contentElement = e.target;
    } else {
      contentElement = findContentParent(e.target);
    }

    console.log(contentElement);

    if(touchStart > movedTo) {
      contentElement.style.transform = `translate3d(${-Math.abs(touchStart - movedTo)}px, 0px, 0px)`;
    } else {
      contentElement.style.transform = `translate3d(${Math.abs(touchStart - movedTo)}px, 0px, 0px)`;
    }
  };

  const handleTouchEnd = function(e) {
    let contentElement = e.target;
    if(contentElement.className !== 'content') {
      contentElement = findContentParent(contentElement);
    }
    let a = parseInt(contentElement.style.transform.split('(')[1]);
    if(Math.abs(a) > contentElement.offsetWidth/2) {
      swipeOut(a, contentElement);
    } else {
      snapBack(a, contentElement);
    }
  };

  const snapBack = function(currentTransform, element) {
    let interval = setInterval(() => {
      if(currentTransform > 0) {
        element.style.transform = `translate3d(${currentTransform - 5}px, 0px, 0px)`;
        currentTransform -= 5;
      } else {
        element.style.transform = `translate3d(${currentTransform + 5}px, 0px, 0px)`;
        currentTransform += 5;
      }

      if(Math.abs(currentTransform) <= 5) {
        element.style.transform = `translate3d(0px, 0px, 0px)`;
        clearInterval(interval);
      }

      if(currentTransform === 0) {
        clearInterval(interval);
      }
    }, 10);
  };

  const composeListItem = function(content) {
    let listItem = document.createElement('div');
    listItem.className = 'swipe-out-list-item';
    listItem.style.cssText = 'position: relative; height: 100px; transition: height .5s;';
    let contentElement = document.createElement('div');
    contentElement.className = 'content';
    contentElement.style.cssText = 'box-sizing: border-box; background-color: white; position:absolute; top: 0; left: 0; border-bottom: solid 1px blue; min-height: 2em; width: 100%; height: 100%;';
    if(content.nodeType === Node.ELEMENT_NODE) {
      contentElement.appendChild(content);
    } else {
      contentElement.innerText = content;
    }

    listItem.appendChild(contentElement);
    let backgroundElement = document.createElement('div');
    backgroundElement.className = 'background';
    backgroundElement.style.cssText = 'display: flex; align-items: center; justify-content: space-between; transition: all 0.5s; z-index: -1; background-color: red; position: absolute; top: 0; left: 0; width: 100%; height: 100%;';
    backgroundElement.innerHTML = `
      <div style="transition: all .5s;">trash</div>
      <div style="transition: all .5s;">trash</div>
    `;
    listItem.appendChild(backgroundElement);
    return listItem;
  };

  const swipeOut = function(currentTransform, element) {
    let interval = setInterval(() => {
      if(currentTransform > 0) {
        element.style.transform = `translate3d(${currentTransform + 5}px, 0px, 0px)`;
        currentTransform += 5;
      } else {
        element.style.transform = `translate3d(${currentTransform - 5}px, 0px, 0px)`;
        currentTransform -= 5;
      }

      if(Math.abs(currentTransform) >= element.offsetWidth + 20) {
        const parent = element.parentNode;
        parent.removeChild(element);
        parent.style.height = '0px';
        parent.children[0].children[0].style.opacity = 0;
        parent.children[0].children[1].style.opacity = 0;
        setTimeout(() => {
          parent.parentNode.removeChild(parent);
        }, 500);
        clearInterval(interval);
      }
    }, 5);
  };

  for (let i = 0; i < items.length; i++) {
    listElement.appendChild(composeListItem(items[i]));

  }

  let array2 = document.querySelectorAll('.content');

  for(let i = 0; i < array2.length; i++) {
    array2[i].addEventListener('touchstart', function(e) {
      touchStart = e.touches[0].clientX;
    })
    array2[i].addEventListener('touchmove', fja);
    array2[i].addEventListener('touchend', handleTouchEnd);
  }

};
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-21 06:03:47

所以首先...只是直截了当的猜测,因为我从未尝试过这样的事情。

好了,我们走吧,请看一下我包含的code =)

代码语言:javascript
复制
// ------------ // 
// DOM ELEMENTS //
// ------------ // 
const div_moveArea = document.getElementById("moveArea");
const label_moveAxis = document.getElementById("moveAxis");

// ------- // 
// GLOBALS //
// ------- //
var lastMouseEvent = null;

// --------------- // 
// EVENT LISTENERS //
// --------------- // 

div_moveArea.addEventListener("mousemove", event => {
    if(!lastMouseEvent) {
        lastMouseEvent = event;
        return;
    }
    // Get the difference
    let difX = lastMouseEvent.clientX - event.clientX;
    let difY = lastMouseEvent.clientY - event.clientY;
    // Normalize them to a positive value
    if(difX < 0) difX *= -1;
    if(difY < 0) difY *= -1;
    // Get the direction 
    if(difX > difY) label_moveAxis.innerText = "Axis: Horizontal";
    else if(difX < difY) label_moveAxis.innerText = "Axis: Vertical";
    
    else {
        // Should be called if both are the same ... use prefered axis here
    }
    lastMouseEvent = event;
});
代码语言:javascript
复制
#moveArea {
    border: 1px solid gray;
    display: block;
    height: 150px;
    width: 300px;
}
代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
    <div id="moveArea">Move mouse over this</div>
    <label id="moveAxis">Axis: NONE</label>
</body>
</html>

注意:您可能希望有一个仅当同一轴多次返回时才更改轴的计数。

祝你今天愉快,Elias :)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52430633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档