javascript - Drag'n'drop:当我单击元素时,元素不会停留在其原始位置
问题描述
我正在为我的一个项目编写自己的拖放功能,但遇到了问题。我所有的“可拖动”元素都在一个带有display:flex
. 在其中一个元素上的 mousedown 事件中,我将其设置为position
,absolute
以便在拖动时能够设置元素的left
和top
属性。这是我正在做的事情:
let container = document.querySelector("#big-container")
var dragging = false;
var draggedObject;
let shiftX=0;
let shiftY=0;
document.querySelectorAll(".draggable").forEach((draggable,index) => {
draggable.style.order = index;
draggable.draggable =false;
draggable.ondragstart = ()=>{return false}
draggable.addEventListener("mousedown",ev =>{
draggedObject = draggable;
shiftX = ev.offsetX+5;
shiftY = ev.offsetY+5;
draggable.style.position = "absolute";
draggable.style.left = (ev.clientX - shiftX) + 'px';
draggable.style.top = (ev.clientY - shiftY) + 'px';
dragging = true;
let placeholder = document.createElement("div");
placeholder.id = "placeholder";
placeholder.style.order = draggable.style.order;
container.appendChild(placeholder);
})
})
document.addEventListener("mousemove", ev =>{
if(dragging){
draggedObject.style.left = ev.clientX - shiftX + 'px';
draggedObject.style.top = ev.clientY - shiftY + 'px';
}
})
document.addEventListener("mouseup",ev =>{
if(dragging){
draggedObject.style.position = 'static'
let placeholder = document.querySelector("#placeholder");
container.removeChild(placeholder);
dragging = false
}
})
/* the :not(:last-of-type(div)) is there so the console doesn't get affected */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: black;
}
.draggable {
width: 90px;
height: 120px;
margin: 5px;
}
#placeholder {
width: 90px;
height: 120px;
margin: 5px;
background-color: rgba(0, 0, 0, 0.3);
border: dashed grey 5px;
}
<body draggable="false" ondragstart="return false;">
<div id = "big-container" style ="display: flex; background-color: rgb(76, 104, 95); width: 500px; height: 500px;">
<div style="background-color: rgb(204, 125, 111);" class="draggable"></div>
<div style="background-color: rgb(170, 214, 120);" class="draggable"></div>
<div style="background-color: rgb(129, 212, 167);" class="draggable"></div>
<div style="background-color: rgb(162, 137, 196);" class="draggable"></div>
</div>
</body>
我想要实现的是,在 mousedown 时,元素应该保持在原来的位置,然后当我移动鼠标来移动元素时。(锚点应该是我单击元素的位置)我这样做shiftX = ev.offsetX+5;
是因为我需要考虑元素的边距。
问题是当我单击一个元素(并且根本不移动鼠标)时,您会看到元素位置发生了一点变化。它非常小(可能是 1 或 2px)并且并非在所有地方都发生(元素中的某些区域不会引入这种位置偏移)
你们知道可能是什么原因造成的吗?
解决方案
您可以使用getBoundingClientRect()
来获取实际位置。
let container = document.querySelector("#big-container");
var dragging = false;
var draggedObject;
let shiftX = 0;
let shiftY = 0;
document.querySelectorAll(".draggable").forEach((draggable, index) => {
draggable.style.order = index;
draggable.draggable = false;
draggable.ondragstart = () => {
return false;
};
draggable.addEventListener("mousedown", (ev) => {
draggedObject = draggable;
var x = draggable.getBoundingClientRect().top - 5;
var y = draggable.getBoundingClientRect().left - 5;
shiftX = ev.offsetX + 5;
shiftY = ev.offsetY + 5;
draggable.style.position = "absolute";
draggable.style.left = y + "px";
draggable.style.top = x + "px";
dragging = true;
let placeholder = document.createElement("div");
placeholder.id = "placeholder";
placeholder.style.order = draggable.style.order;
container.appendChild(placeholder);
});
});
document.addEventListener("mousemove", (ev) => {
if (dragging) {
draggedObject.style.left = ev.clientX - shiftX + "px";
draggedObject.style.top = ev.clientY - shiftY + "px";
}
});
document.addEventListener("mouseup", (ev) => {
if (dragging) {
draggedObject.style.position = "static";
let placeholder = document.querySelector("#placeholder");
container.removeChild(placeholder);
dragging = false;
}
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: black;
}
#big-container {
width: 500px;
height: 500px;
}
.draggable {
width: 90px;
height: 120px;
margin: 5px;
}
#placeholder {
width: 90px;
height: 120px;
margin: 5px;
background-color: rgba(0, 0, 0, 0.3);
border: dashed grey 5px;
}
<body draggable="false" ondragstart="return false;">
<div
id="big-container"
style="display: flex; background-color: rgb(76, 104, 95);"
>
<div
style="background-color: rgb(204, 125, 111);"
class="draggable"
></div>
<div
style="background-color: rgb(170, 214, 120);"
class="draggable"
></div>
<div
style="background-color: rgb(129, 212, 167);"
class="draggable"
></div>
<div
style="background-color: rgb(162, 137, 196);"
class="draggable"
></div>
</div>
</body>
推荐阅读
- python - 如何使用 pyspark 解析 xml 文件并将其转换为数据框?
- excel - 如何仅使用 VBA 在一张纸上将多个范围导出为 PDF
- javascript - 如果用户两次选择相同的项目,ReactJS 语义 UI 下拉菜单不会触发
- firebase - 如果使用默认服务帐户,如何在 Firebase 中覆盖 Google Cloud 项目?(去管理员 SDK)
- android - 反应本机获取抛出异常网络请求在android上失败
- laravel - 简单的 Laravel Passeport 路由测试
- syntax - 为什么使用 ODE 系统在八度音阶中给出语法错误
- dialogflow-es - 使用 Google 转录短音频的问题(是,否)
- c# - 从 excel 文件中替换无效的 XML 字符并将其写回磁盘会导致文件在 MS Excel 中打开时出现损坏错误
- c# - 如何在 mongo DB 中保存对先前版本对象的引用