问题原因
先上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#app {
300px;
height: 300px;
border: 1px solid gray;
position: relative;
margin: 0 auto;
}
div.circle {
position: absolute;
30px;
height: 30px;
line-height: 30px;
background-color: red;
text-align: center;
border-radius: 50%;
}
</style>
</head>
<body>
<div id="app" onclick="handleClick()"></div>
<script>
const app = document.getElementById('app')
let index = 0
function handleClick() {
index++
const div = document.createElement('div')
const span = document.createElement('span')
div.classList.add('circle')
const left = event.offsetX
const top = event.offsetY
console.log(left, top);
span.textContent = index
div.style.left = left - 15 + 'px'
div.style.top = top - 15 + 'px'
div.appendChild(span)
app.appendChild(div)
}
</script>
</body>
</html>
直接使用offsetX/offsetY来定位鼠标点击位置,多次点击同一位置,offsetX/offsetY值会改变
如上图所示,除第一个节点外,其他节点全部跑到了左上角,查看打印日志可以看到offsetX/offsetY都变成了15
造成这个问题的原因是啥呢?
我们看一看offsetX是咋个定义的
MouseEvent 接口的只读属性 offsetX 规定了事件对象与目标节点的内填充边(padding edge)在 X 轴方向上的偏移量。
可以看出offsetX的值是根据目标节点(event.target)的变化而变化的,当我们第二次点击的时候,其实目标节点已变成了<span>1</span>
解决办法
问题已经很清楚了,我们需要把目标节点变成当前的根节点(div#app)
我们可以使用currentTarget结合clientX/clientY来计算鼠标当前点击位置
Event 接口的只读属性 currentTarget 表示的,标识是当事件沿着 DOM 触发时事件的当前目标。它总是指向事件绑定的元素,而 Event.target 则是事件触发的元素。
const app = document.getElementById('app')
let index = 0
function handleClick() {
index++
const div = document.createElement('div')
const span = document.createElement('span')
div.classList.add('circle')
const rect = event.currentTarget.getBoundingClientRect()
const left = event.clientX - rect.left
const top = event.clientY - rect.top
console.log(left, top);
span.textContent = index
div.style.left = left - 15 + 'px'
div.style.top = top - 15 + 'px'
div.appendChild(span)
app.appendChild(div)
}
成功! 多次点击后top/left值仍在同一点