【问题标题】:Problems implementing dragging by mouse实现鼠标拖动的问题
【发布时间】:2018-08-19 14:23:51
【问题描述】:

我想实现一个包含某些元素的可拖动地图。

--> 见 JSFiddle:https://jsfiddle.net/7ndx7s25/7/

通过使用mousedownmousemovemouseup我实现了拖动。 但是我遇到了问题:

  1. 当按下鼠标按钮然后移出窗口时,我没有收到mouseup 事件。重新进入窗口(很久以前释放了鼠标按钮)我的地图仍然认为按钮已按下并相应地行为不端。

  2. 当地图上有对象时,我在穿过这些对象时不会收到mousemove 事件。因此,当我进入和离开这样的对象时,地图会挂起并跳跃。

  3. 虽然在这样的对象上,我仍然想要一个move 鼠标光标。我可以更改每个对象的cursor 样式(在小提琴中,我以对象 1 为例),但这似乎不是一个好方法。有没有更优雅的解决方案?

【问题讨论】:

  • 我的回答中缺少某些内容,或者您​​只是没有时间检查一下?
  • @LGSon 没有时间回答 :-) 就像一个魅力。 mouseoutmouseleave 之间的区别特别有用——我不知道。
  • 谢谢...而且效果很好:)

标签: javascript mouseevent


【解决方案1】:

你需要例如离开canvas 时捕捉mouseout,尽管当光标移到其他元素上时也会触发该事件。

一个简单的解决方法是简单地向canvas 添加一个类,在这些上设置pointer-events: none

使用该类,您也可以控制光标,避免使用脚本进行设置。

堆栈sn-p

updateInfo = function() {
  document.getElementById('info').innerHTML =
    'Position = ' + JSON.stringify(position) +
    '<br />dragInfo = ' + JSON.stringify(dragInfo);
};

const canvas = document.getElementsByTagName('canvas')[0];

let position = { x: 0, y : 0 };
let dragInfo = null;
updateInfo();

canvas.addEventListener('mousedown', function(e) {  
  dragInfo = {
    startEvent: {
      x: e.clientX,
      y: e.clientY,
    },
    startPosition: position
  };
  canvas.classList.add('dragging');
  updateInfo();
});

canvas.addEventListener('mousemove', function(e) {  
  if (dragInfo === null) return;
  
  position = {
    x: dragInfo.startPosition.x - (e.clientX - dragInfo.startEvent.x),
    y: dragInfo.startPosition.y - (e.clientY - dragInfo.startEvent.y)
  };
  updateInfo();
});

canvas.addEventListener('mouseup', function(e) {  
  dragInfo = null;
  canvas.classList.remove('dragging');
  updateInfo();
});

canvas.addEventListener('mouseout', function(e) {
  dragInfo = null;
  canvas.classList.remove('dragging');
  updateInfo();
});
* {
  user-select: none;
  font-family: monospace;
}
canvas {
  background: black;
  border: 1px solid red;
}
.dragging {
  cursor: move;
}
.obj {
  position: absolute;
  width: 50px;
  height: 50px;
  background: green;
  color: white;
  text-align: center;
  line-height: 50px;
  font-weight: bold;
}
.dragging ~ .obj {
  pointer-events: none;
}
<div id="myMap-ish">
  <canvas width="500" height="300"></canvas>
  <div class="obj" style="left: 30px; top: 35px">1</div>
  <div class="obj" style="left: 175px; top: 79px">2</div>
  <div class="obj" style="left: 214px; top: 145px">3</div>
  <div class="obj" style="left: 314px; top: 215px">4</div>
</div>
<div id="info"></div>

另一种选择是在外部包装器上使用mouseleavemyMap-ish 元素,它可以与上面添加的类结合起来以简单地处理光标。

mouseoutmouseleave 之间的主要区别在于后者在悬停子项时不会触发,如下示例所示,因此我们不需要像第一个示例中那样切换 pointer-events .

注意,在第一个示例中,在canvas 上简单地使用mouseleave,将有与mouseout 相同的问题,因为“其他元素”不是canvas 的子元素。

堆栈sn-p

updateInfo = function() {
  document.getElementById('info').innerHTML =
    'Position = ' + JSON.stringify(position) +
    '<br />dragInfo = ' + JSON.stringify(dragInfo);
};

const canvas = document.getElementById('myMap-ish');

let position = { x: 0, y : 0 };
let dragInfo = null;
updateInfo();

canvas.addEventListener('mousedown', function(e) {  
  dragInfo = {
    startEvent: {
      x: e.clientX,
      y: e.clientY,
    },
    startPosition: position
  };
  canvas.style.cursor = 'move';
  document.querySelectorAll('.obj')[0].style.cursor = 'move'; // TODO for all objects
  updateInfo();
});

canvas.addEventListener('mousemove', function(e) {  
  if (dragInfo === null) return;
  
  position = {
    x: dragInfo.startPosition.x - (e.clientX - dragInfo.startEvent.x),
    y: dragInfo.startPosition.y - (e.clientY - dragInfo.startEvent.y)
  };
  updateInfo();
});

canvas.addEventListener('mouseup', function(e) {  
  dragInfo = null;
  canvas.style.cursor = 'default';
  document.querySelectorAll('.obj')[0].style.cursor = 'default';  // TODO for all objects
  updateInfo();
});

canvas.addEventListener('mouseleave', function(e) {  
  dragInfo = null;
  canvas.style.cursor = 'default';
  document.querySelectorAll('.obj')[0].style.cursor = 'default';  // TODO for all objects
  updateInfo();
});
* {
  user-select: none;
  font-family: monospace;
}
canvas {
  background: black;
  border: 1px solid red;
}
.obj {
  position: absolute;
  width: 50px;
  height: 50px;
  background: green;
  color: white;
  text-align: center;
  line-height: 50px;
  font-weight: bold;
}
<div id="myMap-ish">
  <canvas width="500" height="300"></canvas>
  <div class="obj" style="left: 30px; top: 35px">1</div>
  <div class="obj" style="left: 175px; top: 79px">2</div>
  <div class="obj" style="left: 214px; top: 145px">3</div>
  <div class="obj" style="left: 314px; top: 215px">4</div>
</div>
<div id="info"></div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-02
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多