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

问题描述 投票:0回答:1

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

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);
  }

};
javascript swipe touch-event
1个回答
1
投票

所以首先......直接猜测,因为我从未尝试过类似的东西。

好吧,我们去看看我的包含的代码=)

// ------------ // 
// 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;
});
#moveArea {
    border: 1px solid gray;
    display: block;
    height: 150px;
    width: 300px;
}
<!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 :)

© www.soinside.com 2019 - 2024. All rights reserved.