如何使用原生JavaScript限制拖拽元素在指定容器Div内移动?
实现拖拽元素限制在指定容器内的原生JS方案
核心思路
要禁止拖拽元素移出.fill_in_the_gaps--container容器,关键要做到两点:
- 仅允许容器内的合法目标区域(答案填空位、答案备选容器)接受拖拽放置
- 容器外区域不响应拖拽放置操作,拖拽到外部时元素自动返回原位置
修改后的完整代码
JavaScript 部分
// const gapFillAnswers = ["goods & services","opportunities","water","sports car","tangible","intangible","entrepreneurs"]; const answerSpaces = document.querySelectorAll(".fill_in_the_gaps--answer_space"); const answerContainer = document.querySelector(".fill_in_the_gaps--answers_container"); const mainContainer = document.querySelector(".fill_in_the_gaps--container"); const answerWords = document.querySelectorAll(".fill_in_the_gaps--answers"); // 给合法区域绑定事件 answerContainer.addEventListener('drop', dropHandler); answerContainer.addEventListener('dragover', dragOverHandler); answerWords.forEach(element => { element.addEventListener('dragstart', dragStartHandler); element.addEventListener('dragend', dragEndHandler); }); answerSpaces.forEach(element => { element.addEventListener('drop', dropHandler); element.addEventListener('dragover', dragOverHandler); element.addEventListener('dragenter', dragEnterHandler); element.addEventListener('dragleave', dragLeaveHandler); }); // 给主容器绑定dragover,确保容器内空白区域可拖过 mainContainer.addEventListener('dragover', dragOverHandler); // 全局阻止外部区域的drop默认行为,确保外部无法放置 document.addEventListener('dragover', (e) => { if (!mainContainer.contains(e.target)) { e.preventDefault(); } }); function dropHandler(e) { e.preventDefault(); const elementId = e.dataTransfer.getData("text"); const elementToDrop = document.getElementById(elementId); if (!elementToDrop) return; // 目标不在主容器内,直接返回,元素自动回原位 if (!mainContainer.contains(e.target)) { return; } let target = e.target; // 处理拖到主容器空白处的情况,放回答案容器 if (target === mainContainer) { answerContainer.append(elementToDrop); return; } // 处理答案填空位的放置逻辑 if (target.classList.contains("fill_in_the_gaps--answer_space")) { target.style.border = "none"; // 如果填空位已有元素,先将其放回答案容器 if (target.firstChild) { answerContainer.append(target.firstChild); } target.append(elementToDrop); } // 处理答案容器的放置逻辑 else if (target.classList.contains("fill_in_the_gaps--answers_container")) { target.append(elementToDrop); } } function dragOverHandler(e) { e.preventDefault(); } function dragStartHandler(e) { e.target.style.opacity = "0.5"; e.dataTransfer.setData("text", e.target.getAttribute("id")); } function dragEndHandler(e) { e.target.style.opacity = "1"; } function dragEnterHandler(e) { e.target.style.border = "2px dotted green"; } function dragLeaveHandler(e) { e.target.style.border = "none"; }
CSS 部分(保留原样式)
*{ box-sizing: border-box; } :root{ --blue: #000724; --pink: #DC398D; --yellow:#FEBD31; --green:#36F906; } body{ background-color: var(--blue); } .fill_in_the_gaps--container{ padding: 1rem; border-radius: 0.5rem; border-color: var(--pink); border-width: 5px; border-style: solid; background-color: whitesmoke; } .fill_in_the_gaps--answers_container{ display: flex; flex-direction: row; align-items: center; justify-content: space-around; overflow-y: scroll; padding: 1rem; border:2px dotted gray; } .fill_in_the_gaps--answers{ display: inline-block; white-space:nowrap; margin-left: 15px; margin-right: 15px; } .fill_in_the_gaps--answer_space{ display: inline-block; background-color: var(--yellow); width:8rem; height: 1rem; margin-top: 2px; margin-left: 2px; margin-right: 2px;; text-align: center; padding-bottom:2px; vertical-align:middle; }
HTML 部分(保留原结构)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>拖拽填空游戏</title> <script src="app.js" defer></script> <link rel="stylesheet" href="style.css"> </head> <body> <div data-board="aqa" data-level="gcse" data-subject="business" data-unit="1.1" data-type="fill_in_the_gaps" class="fill_in_the_gaps--container"> <p class="fill_in_the_gaps--main_text"> A business is an organisation that produces<span id="answer_space_0" class="fill_in_the_gaps--answer_space"></span>.Often businesses are setup to take advantage of business <span id="answer_space_1" class="fill_in_the_gaps--answer_space"></span>. Many businessess sell items that people need, some businesses sell items that people want. An example of a need is <span id="answer_space_2" class="fill_in_the_gaps--answer_space"></span>. An example of a want is a <span id="answer_space_3" class="fill_in_the_gaps--answer_space"></span>. Goods are an example of <span id="answer_space_4" class="fill_in_the_gaps--answer_space"></span>items. Services are an example of <span id="answer_space_5" class="fill_in_the_gaps--answer_space"></span>items. People who start up a business are known as <span id="answer_space_6" class="fill_in_the_gaps--answer_space"></span>their reward for taking a risk is profit. </p> <div class="fill_in_the_gaps--answers_container"> <span id="answer_0" draggable="true" class="fill_in_the_gaps--answers">goods & services</span> <span id="answer_1" draggable="true" class="fill_in_the_gaps--answers">opportunities</span> <span id="answer_2" draggable="true" class="fill_in_the_gaps--answers">water</span> <span id="answer_3" draggable="true" class="fill_in_the_gaps--answers">sports car</span> <span id="answer_4" draggable="true" class="fill_in_the_gaps--answers">tangible</span> <span id="answer_5" draggable="true" class="fill_in_the_gaps--answers">intangible</span> <span id="answer_6" draggable="true" class="fill_in_the_gaps--answers">entrepreneurs</span> </div> </div> </body> </html>
关键修改点说明
- 添加主容器引用:获取
.fill_in_the_gaps--container元素,用于后续判断目标区域是否在容器内 - 全局拖拽事件控制:给
document绑定dragover事件,阻止容器外区域的默认拖拽行为,确保外部无法接受放置 - 完善放置逻辑:
- 检查放置目标是否在主容器内,不在则直接返回,元素自动回到原位置
- 处理拖到容器空白处的情况,将元素放回答案备选容器
- 增加填空位的元素替换逻辑,避免一个空位放多个元素
内容的提问来源于stack exchange,提问作者jon
相关产品推荐
相关产品推荐

