javascript - 触摸移动的工作方式与鼠标移动不同
问题描述
如果有三个 div div1,div2,div3 并排。如果我在 div1 上执行 mousedown,然后如果我将鼠标移动到 div2 上,则 div2 mousemove 将被触发,目标为 div2。但是在移动设备中,如果在 div1 上执行相同的操作,甚至 mousedown(touchstart) 并将鼠标移动到 div2 上,那么 mousemove(touchmove) 就会以目标作为 div1 本身触发。我需要移动 touchmove 事件目标作为 div2?
为什么行为会有所不同,我们能做什么?
以下是我为解释我的问题所做的示例,
var testString = '';
handleMouseMoveListener = (e) => {
//console.log(e.target.id);
e.preventDefault();
e.stopPropagation();
this.testString = this.testString + ' ' + e.target.id;
}
handleMouseUpHandler = (e) => {
alert(this.testString);
this.testString = '';
}
let elementsArray = document.querySelectorAll("div");
elementsArray.forEach(function (elem) {
elem.addEventListener('mousemove', this.handleMouseMoveListener);
elem.addEventListener('touchmove', this.handleMouseMoveListener);
elem.addEventListener('mouseup', this.handleMouseUpHandler);
elem.addEventListener('touchend', this.handleMouseUpHandler);
});
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
div {
display: inline-block;
width: 150px;
height: 150px;
color: red;
border: 1px solid black;
}
</style>
</head>
<body>
<div id='div1'>div1</div>
<div id='div2'>div2</div>
<div id='div3'>div3</div>
</body>
</html>
解决方案
这是规范定义的行为:
此事件的目标必须与触摸点第一次放置在表面上时开始的元素相同,即使触摸点已经移出目标元素的交互区域也是如此。
至于为什么以这种方式定义...我不太确定,但我认为它可以追溯到 iphone 在市场上单独出现的时候,并且规范只是接受了他们的行为,因为这对我们的网络开发人员来说可能是违反直觉的.
对于我们能做什么,之前已经被询问和回答:您可以使用您的 Touch 实例将公开document.elementFromPoint()
的clientX
和值:clientY
if( document.ontouchmove === undefined ) {
console.log( "please enable your dev-tools's Responsive mode" );
}
document.querySelectorAll( '.container div' ).forEach( (elem) => {
elem.addEventListener( 'touchstart', prevent );
elem.addEventListener( 'touchmove', handleTouchMove );
} );
function handleTouchMove( evt ) {
//prevent( evt );
deactivateTarget(); // clean
evt.target.classList.add( 'target' ); // make the official target's text red
const touch = evt.changedTouches[ 0 ];
const actualTarget = document.elementFromPoint( touch.clientX, touch.clientY );
if( actualTarget ) {
actualTarget.classList.add( 'active' ); // make the hovered element green
}
}
function deactivateTarget() {
document.querySelectorAll( '.active,.target' ).forEach( (elem) => {
elem.classList.remove( 'active', 'target' );
})
}
function prevent( evt ) {
evt.preventDefault();
}
.container div {
display: inline-block;
width: 150px;
height: 50px;
border: 1px solid black;
}
.container div.active {
background: green;
}
.container div.target {
color: red;
}
<div class="container">
<div>div1</div>
<div>div2</div>
<div>div3</div>
<div>div4</div>
<div>div5</div>
<div>div6</div>
<div>div7</div>
<div>div8</div>
<div>div9</div>
<div>div10</div>
<div>div11</div>
<div>div12</div>
<div>div13</div>
<div>div14</div>
<div>div15</div>
</div>
推荐阅读
- mysql - 其中包含 STR_TO_DATE 和 SUBSTRING
- python - 获取 jupyter notebook 以打印它已导入的整个函数
- javascript - React.js 表单 - 如何在最后一页包含所有值?
- mysql - 执行此 INSERT 语句时,我应该更改什么以避免 Aurora MySQL 错误 1034?
- python - 无法读取正确的 buildozer logcat
- node.js - 反应,节点:变量在 app.post() 上显示未定义
- javascript - ajax, jquery with mysql query in js - 这可能吗?
- javascript - $.get 返回相同的数组
- node.js - 未使用 REST API 在 Node Js 中调用函数
- regex - 基于排除字符集的Python正则表达式搜索