从 javascript 中的触摸事件中排除滚动
Exclude scroll from touch events in javascript
我正在尝试在 javascript 中创建一个滑动列表,类似于 android 中的 Gmail 应用程序。我正在使用 touchstart
、touchmove
和 touchend
等事件。当我向左或向右滑动列表项时,一切正常,但是当我尝试向下滚动列表时,它会移动我手指所在的列表项(因为我在滚动时不会完全垂直拖动手指)。有没有一种简单的方法可以通过区分滑动事件和滚动事件或类似事件来解决这个问题?
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);
}
};
所以首先...只是直接猜测,因为我从未尝试过类似的事情。
好吧,我们走吧,请看一下我包含的代码=)
// ------------ //
// 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>
注意:您可能希望只有在同一轴返回几次时才更改轴的计数。
祝你今天愉快,伊莱亚斯 :)
我正在尝试在 javascript 中创建一个滑动列表,类似于 android 中的 Gmail 应用程序。我正在使用 touchstart
、touchmove
和 touchend
等事件。当我向左或向右滑动列表项时,一切正常,但是当我尝试向下滚动列表时,它会移动我手指所在的列表项(因为我在滚动时不会完全垂直拖动手指)。有没有一种简单的方法可以通过区分滑动事件和滚动事件或类似事件来解决这个问题?
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);
}
};
所以首先...只是直接猜测,因为我从未尝试过类似的事情。
好吧,我们走吧,请看一下我包含的代码=)
// ------------ //
// 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>
注意:您可能希望只有在同一轴返回几次时才更改轴的计数。
祝你今天愉快,伊莱亚斯 :)