简体   繁体   English

为什么我的 mousedown 事件会在 mouseup 事件上触发?

[英]Why is my mousedown event triggered on a mouseup event?

I've been working on the etch-a-sketch project of the Odin project , and I came across some weird behavior when implementing the mousedown and mouseup event listeners.我一直在研究Odin 项目的 etch-a-sketch 项目,在实现mousedownmouseup事件侦听器时遇到了一些奇怪的行为。

I've created a 50x50 grid of divs in a container div.我在容器 div 中创建了一个 50x50 的 div 网格。 The container div listens on mousedown events, upon which it calls the startDrawing function, filling the boxes that the user hovers over.容器 div 监听mousedown事件,在此事件上它调用startDrawing function,填充用户悬停的框。 It also listens on mousedown events, so that when the mouse is released, the stopDrawing function is called and the filling of boxes stops.它还监听mousedown事件,因此当释放鼠标时,将stopDrawing function 并停止填充框。

All of this works pretty much fine, but sometimes when I start drawing a line with the mouse left button held down, the box div becomes "grabbed".所有这些都工作得很好,但有时当我按住鼠标左键开始画一条线时,盒子 div 变成了“抓取”。 After this, while dragging the mouse with the left button still down, the boxes are not filled when hovering over them.此后,在按住左键的情况下拖动鼠标时,将鼠标悬停在框上时不会填充框。 Then when I release the mouse it starts drawing.然后当我释放鼠标时,它开始绘图。 It's as if the behavior is toggled after the accidental "grabbing", but on the next mousedown it starts acting normally again.就好像在意外“抓取”后切换了行为,但在下一次鼠标按下时,它又开始正常运行。

This is probably harder to explain than to see it for yourself, so below is my code as well as a link to a corresponding codepen.这可能比自己看更难解释,所以下面是我的代码以及相应代码笔的链接。

I've tried googling to find out how I can remove this "grabbing" behavior, but I haven't really found anything, probably because I don't even know what keywords to search for.我试过用谷歌搜索找出如何消除这种“抓取”行为,但我还没有真正找到任何东西,可能是因为我什至不知道要搜索什么关键字。

Can somebody explain what's happening and provide some info on how I can fix this?有人可以解释发生了什么并提供一些有关如何解决此问题的信息吗?

Etch-a-Sketch Codepen Etch-a-Sketch Codepen

 const GRID_SIZE = 50; for(let i = 0; i < GRID_SIZE * GRID_SIZE; i++){ const container = document.getElementById('container'); let div = document.createElement('div'); div.classList.add('box'); container.appendChild(div); } function fillBox(e){ this.classList.add('filled'); } function clearGrid(){ const boxes = document.querySelectorAll('.box'); boxes.forEach(box => box.classList.remove('filled')); } function startDrawing(){ // console.log("start drawing"); const boxes = document.querySelectorAll('.box'); boxes.forEach(box => box.addEventListener('mouseover', fillBox)); } function stopDrawing(){ // console.log("stop drawing"); const boxes = document.querySelectorAll('.box'); boxes.forEach(box => box.removeEventListener('mouseover', fillBox)); } const container = document.querySelector('#container'); container.addEventListener('mousedown', startDrawing); container.addEventListener('mouseup', stopDrawing); const button = document.querySelector('#clear-grid-btn'); button.onclick = clearGrid;
 #container{ width: 500px; display: grid; grid-template-columns: repeat(50, 10px); grid-template-rows: repeat(50, 10px); border: solid; border-color: black; margin:auto; }.box{ width: 10px; height: 10px; }.box:hover{ background-color: blue; }.filled{ background-color: blue; } #clear-grid-btn{ display:block; margin:auto; margin-top: 10px; }
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="etch-a-sketch.css"> </head> <body> <div id="container"></div> <button id="clear-grid-btn">Clear grid</button> </body> <script src="etch-a-sketch.js"></script> </html>

What happens here is that the default behavior of a mousedown + mousemove is to initiate a grab.这里发生的是 mousedown + mousemove 的默认行为是启动抓取。
Certainly, at some point, the browser will select some content in the page and start grabbing it.当然,在某些时候,浏览器会 select 页面中的一些内容并开始抓取它。

The solution to avoid this is to tell the browser that your code does handle the event and should thus not perform its usual behavior.避免这种情况的解决方案是告诉浏览器您的代码确实处理了该事件,因此不应执行其通常的行为。 You can do so by calling the Event::preventDefault() method:您可以通过调用Event::preventDefault()方法来做到这一点:

 const GRID_SIZE = 50; for(let i = 0; i < GRID_SIZE * GRID_SIZE; i++){ const container = document.getElementById('container'); let div = document.createElement('div'); div.classList.add('box'); container.appendChild(div); } function fillBox(evt){ evt.preventDefault(); // tell the browser we handle that event this.classList.add('filled'); } function clearGrid(){ const boxes = document.querySelectorAll('.box'); boxes.forEach(box => box.classList.remove('filled')); } function startDrawing(evt){ evt.preventDefault(); // tell the browser we handle that event // console.log("start drawing"); const boxes = document.querySelectorAll('.box'); boxes.forEach(box => box.addEventListener('mouseover', fillBox)); } function stopDrawing(evt){ evt.preventDefault(); // tell the browser we handle that event // console.log("stop drawing"); const boxes = document.querySelectorAll('.box'); boxes.forEach(box => box.removeEventListener('mouseover', fillBox)); } const container = document.querySelector('#container'); container.addEventListener('mousedown', startDrawing); container.addEventListener('mouseup', stopDrawing); const button = document.querySelector('#clear-grid-btn'); button.onclick = clearGrid;
 #container{ width: 500px; display: grid; grid-template-columns: repeat(50, 10px); grid-template-rows: repeat(50, 10px); border: solid; border-color: black; margin:auto; }.box{ width: 10px; height: 10px; }.box:hover{ background-color: blue; }.filled{ background-color: blue; } #clear-grid-btn{ display:block; margin:auto; margin-top: 10px; }
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="etch-a-sketch.css"> </head> <body> <div id="container"></div> <button id="clear-grid-btn">Clear grid</button> </body> <script src="etch-a-sketch.js"></script> </html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM