javascript - 如何拥有可拖放的行列表?
问题描述
我正在开发一个可以在容器之间启用拖放操作的原型。但是,我有一个冲突案例:
- 当我
position: absolute
用于可拖动项目时,它们是可拖动的,但它们彼此重叠:/ - 当我使用它们时
position: relative
,它们均匀分布在它们的容器中,但它们不可拖动:/
我在下面的卡盘中收集了可测试的代码;请让我知道你认为我该如何解决这个问题。
<!DOCTYPE html>
<html>
<head>
<style>
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
.lang1Container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.meaningContainer {
border: 1px solid rgba(15, 15, 15, 0.2);
box-shadow: 0px 0px 5px 10px rgba(138, 57, 57, 0.2);
}
.lang1Item {
width: 300px;
height: 20px;
position: absolute;
background-color: #f44336;
color: #ffffff;
font-family: Oxygen, sans-serif;
font-size: px;
padding: 7px;
box-shadow: inset 1px 1px 10px 0 rgba(138, 57, 57, 0.2);
border-radius: 3px;
cursor: pointer;
}
.snap {
width: 301px;
height: 30px;
margin-top: 25px;
margin-bottom: 25px;
}
.over {
background-color: rgb(158, 89, 87, 0.2);
border: 1px solid #7c5b59;
border-radius: 3px;
border-style: dashed;
}
</style>
</head>
<body>
<div style="display: flex; flex-direction: column">
<div
id="lang1MeaningContainer"
style="
background-color: bisque;
min-width: 300px;
min-height: 400px;
border-color: red;
border-style: dashed;
margin: 10px;
"
>
<div class="header">lang1MeaningContainer - Meaning Container</div>
<div class="snap"></div>
<div class="snap"></div>
<div class="snap"></div>
<div class="snap"></div>
<div class="snap"></div>
<div class="snap"></div>
</div>
<div
id="lang1Container"
style="
background-color: bisque;
min-width: 300px;
min-height: 400px;
border-color: red;
border-style: dashed;
margin: 10px;
display: flex;
flex-direction: column;
"
>
<div class="header">lang1Container - English Words</div>
<div id="item1" class="lang1Item">Lang Item 1</div>
<div id="item2" class="lang1Item">Lang Item 2</div>
<span id="item3" class="lang1Item">Lang Item 3</span>
<span id="item4" class="lang1Item">Lang Item 4</span>
</div>
</div>
<script>
let lang1Container = document.getElementById("lang1Container");
let meaningContainer = document.getElementById("lang1MeaningContainer");
let lang1Items = document.getElementsByClassName("lang1Item");
console.log("length:" + lang1Items.length);
for (let i = 0; i < lang1Items.length; i++) {
let item = lang1Items[i];
item.addEventListener("mousedown", (e) => {
onMouseDown(e, item);
});
document.body.addEventListener("mousemove", (e) => {
onMouseMove(e, item);
});
item.addEventListener("mouseup", (e) => {
onMouseUp(e, item);
});
}
let mouseOffset = { x: 0, y: 0 };
let isMouseDown = false;
// for (let i = 0; i < 6; i++) {
// let snap = document.createElement("div");
// snap.className = "snap";
// meaningContainer.appendChild(snap);
// }
let doElsCollide = function (el1, el2) {
el1.offsetBottom = el1.offsetTop + el1.offsetHeight;
el1.offsetRight = el1.offsetLeft + el1.offsetWidth;
el2.offsetBottom = el2.offsetTop + el2.offsetHeight;
el2.offsetRight = el2.offsetLeft + el2.offsetWidth;
return !(
el1.offsetBottom < el2.offsetTop ||
el1.offsetTop > el2.offsetBottom ||
el1.offsetRight < el2.offsetLeft ||
el1.offsetLeft > el2.offsetRight
);
};
function snapMeaning(item, container) {
let box = container.getBoundingClientRect();
item.style.left = box.x + "px";
item.style.top = box.y + "px";
}
function onMouseDown(e, item) {
isMouseDown = true;
mouseOffset = {
x: item.offsetLeft - e.clientX,
y: item.offsetTop - e.clientY,
};
item.style.backgroundColor = "red";
}
function onMouseMove(e, item) {
e.preventDefault();
if (isMouseDown) {
item.style.left = e.clientX + mouseOffset.x + "px";
let tmpStyle = getComputedStyle(item);
let strMarginTop = tmpStyle.marginTop;
let tmpMarginTop = strMarginTop.replace("px", "");
item.style.top = e.clientY - tmpMarginTop + mouseOffset.y + "px"; // zero margin is used in CSS definition, otherwise margin amount need to be subtracted from the item.style.top value to have a proper event reaction. UU
// checking collusions with snaps
let snaps = document.getElementsByClassName("snap");
//console.log("Started checking");
for (let i = 0; i < snaps.length; i++) {
if (doElsCollide(item, snaps[i])) {
snaps[i].className = "snap over";
//console.log("[" + Date.now() + "]", "Collides with " + i);
} else {
snaps[i].className = "snap";
}
}
//console.log("Ended checking");
}
}
function onMouseUp(e, item) {
isMouseDown = false;
let snaps = document.getElementsByClassName("snap");
for (let i = 0; i < snaps.length; i++) {
if (doElsCollide(item, snaps[i])) {
snapMeaning(item, snaps[i]);
}
}
item.className = "lang1Item";
}
</script>
</body>
</html>
解决方案
推荐阅读
- macos - 为什么 /usr/share/dict/words 在 OSX 上包含“manbird”?
- javascript - 如何使用 wp-blocks api 将原始 html 转换/解析为 wp gutenberg 块?
- node.js - AWS 使用无服务器 lambda 将用户登录到 cognito
- javascript - 当有问题的代码(似乎)不存在时,如何修复“参数列表后丢失”错误?
- kubernetes - k8s - 如何将服务帐户令牌投影到 pod
- angular - 可以将字符串转换为有效条件以在 *ngIf 中使用以过滤数据吗?
- elasticsearch - 将 ReactiveSearch 与电子商务子类别一起使用的示例
- html - 列表中的每个孩子都应该有一个唯一的“关键”道具
- excel - 我将范围设置为最后一行,我想复制它
- php - Eloquent 获取价值 多对多关系