我正在尝试用JavaScript创建一个拖放引擎。现在,我正在添加一个边界功能,它会将.drag
对象捕获到其父元素中。但是,要做到这一点,我需要了解定位如何在html中工作,而我不这样做。任何人都可以彻底解释一下吗?
Javascript引擎:
// JavaScript Document
var posX;
var posY;
var element;
var currentPos;
document.addEventListener("mousedown", drag, false);
function drag(event) {
if(~event.target.className.search(/drag/)) {
element = event.target;
element.style.zIndex="100";
currentPos = findPos(element);
posX = event.clientX -currentPos.x;
posY = event.clientY -currentPos.y;
if(~event.target.className.search(/bound/))
document.addEventListener("mousemove", boundMovement, false);
else
document.addEventListener("mousemove", freeMovement, false);
}
}
function freeMovement(event) { // This functions works
if (typeof(element.mouseup) == "undefined")
document.addEventListener("mouseup", drop, false);
//Prevents redundantly adding the same event handler repeatedly
element.style.left = event.clientX - posX + "px";
element.style.top = event.clientY - posY + "px";
}
function boundMovement(event) { // This function doesn't work
if (typeof(element.mouseup) == "undefined")
document.addEventListener("mouseup", drop, false);
//Prevents redundantly adding the same event handler repeatedly
// Below logic is false- I wish to understand why =]
currentPos = findPos(element.offsetParent);
if((event.clientX - posX) <= currentPos.x)
element.style.left = event.clientX - posX + "px";
if((event.clientY - posY) <= currentPos.y)
element.style.top = event.clientY - posY + "px";
}
function drop() {
element.style.zIndex="1";
document.removeEventListener("mousemove", boundMovement, false);
document.removeEventListener("mousemove", freeMovement, false);
document.removeEventListener("mouseup", drop, false);
//alert("DEBUG_DROP");
}
function findPos(obj) { // Donated by `lwburk` on StackOverflow
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
}
这是我正在使用的CSS:
@charset "utf-8";
/* CSS Document */
.drag {
position: absolute;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.bound {
/* Class to signify that the drag_object can not leave the parent element */
;
}
.square {
width: 100px;
height: 100px;
background: red;
cursor:move;
}
p {
padding: 0px;
margin: 0px;
outline-style: dotted;
outline-color: #000;
outline-width: 1px;
}
一些HTML示例:
<p class="drag bound square">Thing One</p>
<p class="drag square">Thing Two</p>
请注意我包含JavaScript,以便我对如何应用相对于我编写的内容有疑问。另外,谢谢大家的阅读和帮助。 StackOverflow是学习如何用JavaScript编写代码的非凡资源。
编辑:
1)我应该说我正在编写引擎来帮助我学习语言。这是我的第一周JavaScript,我希望能够在使用库之前使用该语言进行编码。
2)例如,我真的希望有人解释偏移在这里是如何工作的。我想知道如何使用position:absolute
而不是使用position:relative
来创建我的JavaScript引擎,我可以使用{{1}},以便元素可以堆叠在彼此之上等。
答案 0 :(得分:2)
我已在http://jsfiddle.net/vJ6r6/发布了解决方案。
首先,我嵌套了要在边界框内拖动的项目:
<div class="bound">Thing One
<div class="drag square">Thing Two</div>
<div class="drag square">Thing Three</div>
</div>
另外,我把它们变成了div,因为p不能嵌套。 (不要忘记更改样式声明。)
然后,我在边界框上设置样式:
<style>
.bound {
margin: 100px;
width: 400px;
height: 400px;
position: relative;
}
</style>
关键属性是position: relative
,它会使其中的项目相对于它而不是页面定位。 请注意,因为我使用相对定位,所以当您想要将项目保留在特定容器中时,此示例效果最佳。
我对JavaScript的更改更激进,所以这就是整个事情:
<script>
var dragInfo;
function down(event) {
if (~event.target.className.search(/drag/)) {
document.addEventListener("mouseup", drop, false);
var t = event.target;
t.style.zIndex = 100;
dragInfo = {
element: t,
// record the bounds
maxX: t.parentNode.offsetWidth - t.offsetWidth,
maxY: t.parentNode.offsetHeight - t.offsetHeight,
// we don't need findPos, because it's no longer relative to the page
posX: event.clientX - t.offsetLeft,
posY: event.clientY - t.offsetTop
};
document.addEventListener("mousemove", freeMovement, false);
}
}
function freeMovement(event) {
// the min and max calculations keep the X and Y within the bounds
dragInfo.element.style.left = Math.max(0, Math.min(event.clientX - dragInfo.posX, dragInfo.maxX)) + "px";
dragInfo.element.style.top = Math.max(0, Math.min(event.clientY - dragInfo.posY, dragInfo.maxY)) + "px";
}
function drop() {
dragInfo.element.style.zIndex = 1;
document.removeEventListener("mousemove", freeMovement, false);
document.removeEventListener("mouseup", drop, false);
}
document.addEventListener("mousedown", down, false);
</script>
注意这一行:
dragInfo.element.style.left = Math.max(0, Math.min(event.clientX - dragInfo.posX, dragInfo.maxX)) + 'px';
等同于:
var x = event.clientX - dragInfo.posX;
if (x < 0) x = 0;
if (x > dragInfo.maxX) x = dragInfo.maxX;
dragInfo.element.style.left = x + 'px';
答案 1 :(得分:1)
我认为问题(至少是你的例子)是当你为findPos
中的有界元素调用boundMovement
函数时,你传递的是它的父节点,它没有它自己的父节点。所以在findPos
函数内部这个特定的行
if (obj.offsetParent) {
// ...
返回undefined,因为它没有父级。尝试删除if语句并再次尝试。
答案 2 :(得分:0)
您可能会觉得这很有帮助 A list Apart's css-positioning 101
你到底遇到了什么问题?
绝对将元素从正常的“文档流”中移除,并允许您将其放置在您想要的位置。
相对位置很像静态,但允许你在其中绝对定位元素。
Static遵循正常的文档流程。 (层叠)
顺便说一句,我建议你使用像JQuery或Prototype这样的库或框架,而不是手工构建它。它将为您节省数小时的挫折感并在不同的浏览器中进行测试。
编辑: 既然你很难做到这一点......我希望我能得到一些帮助。 我建议您下载适用于Firefox的firebug插件,如果这是您使用的,或者在Chrome中使用工具获取熟悉的Javascript控制台。
HTML
<p class="drag bound square">Thing One</p>
<p class="drag square">Thing Two</p>
这里没有父母/子女关系你的意思是文件是边界吗? freeMovement不会在BoundMovement所在的元素offSetParent上调用findPos。 由于文档没有该属性,因此重定义未定义。
尝试将这两个段落包含在body标签以外的其他内容中。
<div id='container'>
<p class="drag bound square">Thing One</p>
<p class="drag square">Thing Two</p>
</div>
答案 3 :(得分:0)
您是否看过这个jQuery演示http://jqueryui.com/demos/draggable/#events
使用jQuery使JavaScript更容易,并且还将确保您的代码跨浏览器工作。