如何检测用户是否正在尝试调整可拖动元素的大小?

van*_*owm 6 html javascript css

我正在尝试创建可拖动元素,这些元素也可以通过在 CSS 规则的帮助下拖动右下角来调整大小resize: both。到目前为止,我可以在屏幕上拖动它,但我不知道如何检测光标是否处于“调整大小”状态,因为尝试调整元素大小会移动它。

目前,作为一种解决方法,我只是检查光标是否在右下角的 20px 范围内,但这不是很准确(可能取决于浏览器/操作系统),并且在某些地方它拒绝调整元素大小或移动元素全部。

有什么建议么?

!function(){
"use strict";
let x, y, drag;
document.addEventListener("mousedown", function(e) {
  if (e.target.parentNode.lastChild !== e.target && e.target.parentNode.classList.contains("main")) {
    //bring element to the front and dispatch mousedown event again otherwise resize doesn't work
    e.target.parentNode.appendChild(e.target);
    return e.target.dispatchEvent(new MouseEvent(e.type, e));
  }

  if (!e.target.classList.contains("draggable"))
    return;

  /* if cursor within 20px from bottom right corner don't move */
  const r = e.target.getBoundingClientRect();
  if (r.right < e.x + 20 && r.bottom < e.y + 20)
    return;

  drag = e.target;
  x = e.x - drag.offsetLeft;
  y = e.y - drag.offsetTop;
  document.body.classList.add("drag");
  drag.classList.add("drag");
});

document.addEventListener("mouseup", function(e) {
  document.body.classList.remove("drag");
  drag = drag && drag.classList.remove("drag");
});

document.addEventListener("mousemove", function(e) {
  if (!drag || e.x - drag.offsetLeft == x || e.y - drag.offsetTop == y)
    return;

  drag.style.left = (e.x - x) + "px";
  drag.style.top = (e.y - y) + "px";
});

/*init*/
for (let i = 0, c, d = document.getElementsByClassName("main")[0].children; i < d.length; i++) {
  c = (0x1000000 + Math.random() * 0xffffff).toString(16).substr(1, 6);
  d[i].style.backgroundColor = '#' + c;
  d[i].classList.toggle("dark", ((parseInt(c.substr(0, 2), 16) * 299) + (parseInt(c.substr(2, 2), 16) * 587) + (parseInt(c.substr(4, 2), 16) * 114)) / 1000 < 128);
  d[i].style.left = document.documentElement.scrollWidth / 8 + Math.random() * (document.documentElement.scrollWidth / 1.33 - d[i].offsetWidth) + "px";
  d[i].style.top = document.documentElement.scrollHeight / 8 + Math.random() * (document.documentElement.scrollHeight / 1.33 - d[i].offsetHeight) + "px";
}
}()
Run Code Online (Sandbox Code Playgroud)
div.main>div {
  width: 5em;
  height: 5em;
  border: 1px solid black;
  position: absolute;
  resize: both;
  overflow: hidden;
  mix-blend-mode: hard-light;
  display: flex;
  border-radius: 0.3em;
}

div.main>div:hover {
  box-shadow: 0 0 5px black;
}

div.main>div:last-child {
  box-shadow: 0 0 10px black;
}

div.draggable {
  cursor: grab;
}

div.main>div:not(.draggable):before {
  content: "can't move me";
}

div.main>div.draggable:before {
  content: "move me";
}

div.main>div:before {
  color: black;
  text-shadow: 0 0 1em black;
  margin: auto;
  text-align: center;
}

div.main>div.dark:before {
  color: white;
  text-shadow: 0 0 1em white;
}

body.drag {
  user-select: none;
}

body.drag div.draggable {
  cursor: grabbing;
}
Run Code Online (Sandbox Code Playgroud)
<div class="main">
  <div></div>
  <div class="draggable"></div>
  <div class="draggable"></div>
  <div class="draggable"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

Kai*_*ido 3

您可以将鼠标目标 ( .draggable) 包装在可调整大小的容器元素内。
这样,CSS 调整大小的 UI 将在可拖动元素之前被命中,并且您可以很好地处理仅拖动:

!function(){
"use strict";
let x, y, drag;
document.addEventListener("mousedown", function(e) {
  if (e.target.parentNode.lastChild !== e.target && e.target.parentNode.classList.contains("main")) {
    //bring element to the front and dispatch mousedown event again otherwise resize doesn't work
    e.target.parentNode.appendChild(e.target);
    return e.target.dispatchEvent(new MouseEvent(e.type, e));
  }

  if (!e.target.classList.contains("draggable"))
    return;

  e.preventDefault();
  drag = e.target.parentNode;
  x = e.x - drag.offsetLeft;
  y = e.y - drag.offsetTop;
  document.body.classList.add("drag");
  drag.classList.add("drag");
});

document.addEventListener("mouseup", function(e) {
  document.body.classList.remove("drag");
  drag = drag && drag.classList.remove("drag");
});

document.addEventListener("mousemove", function(e) {
  if (!drag || e.x - drag.offsetLeft == x || e.y - drag.offsetTop == y)
    return;

  drag.style.left = (e.x - x) + "px";
  drag.style.top = (e.y - y) + "px";
});

/*init*/
for (let i = 0, c, d = document.getElementsByClassName("main")[0].children; i < d.length; i++) {
  c = (0x1000000 + Math.random() * 0xffffff).toString(16).substr(1, 6);
  d[i].style.backgroundColor = '#' + c;
  d[i].classList.toggle("dark", ((parseInt(c.substr(0, 2), 16) * 299) + (parseInt(c.substr(2, 2), 16) * 587) + (parseInt(c.substr(4, 2), 16) * 114)) / 1000 < 128);
  d[i].style.left = document.documentElement.scrollWidth / 8 + Math.random() * (document.documentElement.scrollWidth / 1.33 - d[i].offsetWidth) + "px";
  d[i].style.top = document.documentElement.scrollHeight / 8 + Math.random() * (document.documentElement.scrollHeight / 1.33 - d[i].offsetHeight) + "px";
}
}()
Run Code Online (Sandbox Code Playgroud)
.resizeable {
  width: 5em;
  height: 5em;
  border: 1px solid black;
  position: absolute;
  resize: both;
  overflow: hidden;
  mix-blend-mode: hard-light;
  border-radius: 0.3em;
}

div.main>div:hover {
  box-shadow: 0 0 5px black;
}

div.main>div:last-child {
  box-shadow: 0 0 10px black;
}

div.draggable {
  cursor: grab;
  width: 100%;
  height: 100%;
  display: flex;
}
div.no-drag {
  display: flex;
}
div.main div.no-drag:before {
  content: "can't move me";
}
div.draggable:before {
  content: "move me";
}
div.main div:before {
  color: black;
  text-shadow: 0 0 1em black;
  margin: auto;
  text-align: center;
}

div.main>div.dark:before {
  color: white;
  text-shadow: 0 0 1em white;
}

body.drag {
  user-select: none;
}

body.drag div.draggable {
  cursor: grabbing;
}
Run Code Online (Sandbox Code Playgroud)
<div class="main">
  <div class="resizeable no-drag"></div>
  <div class="resizeable"><div class="draggable"></div></div>
  <div class="resizeable"><div class="draggable"></div></div>
  <div class="resizeable"><div class="draggable"></div></div>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 太棒了!谢谢。我必须调整使元素向前移动的部分(不幸的是我仍然必须在 mousedown 事件中调度鼠标事件),但它可以完美地工作。 (2认同)