浏览器点击同一个位置offsetX/offsetY不一样

问题原因

先上代码

<!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 {
            width: 300px;
            height: 300px;
            border: 1px solid gray;
            position: relative;
            margin: 0 auto;
        }

        div.circle {
            position: absolute;
            width: 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值仍在同一点

posted @ 2021-03-15 17:45  paul_xiao  阅读(769)  评论(0编辑  收藏  举报