Javascript 在HTML/CSS中定位是如何工作的?
我正在尝试用JavaScript制作一个拖放引擎。现在,我正在添加一个边界特性,它将把Javascript 在HTML/CSS中定位是如何工作的?,javascript,html,css,drag-and-drop,Javascript,Html,Css,Drag And Drop,我正在尝试用JavaScript制作一个拖放引擎。现在,我正在添加一个边界特性,它将把.drag对象困在其父元素中。然而,要做到这一点,我需要了解定位在html中是如何工作的,而我不知道。有人能详细解释一下吗 Javascript引擎: // JavaScript Document var posX; var posY; var element; var currentPos; document.addEventListener("mousedown", drag, false); fun
.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 };
}
}
一些HTML示例:
<p class="drag bound square">Thing One</p>
<p class="drag square">Thing Two</p>
第一件事
第二件事
请注意,我包含了JavaScript,这样,如果我对如何应用与我所写内容相关的内容有疑问,就可以使用JavaScript。同时,感谢大家的阅读和帮助。StackOverflow是学习如何使用JavaScript编写代码的一个特殊资源
编辑:
1) 我应该说,我编写引擎是为了帮助我学习语言。这是我学习JavaScript的第一周,我希望在使用库之前能够用这种语言编写代码
2) 例如,我真的希望有人解释一下补偿是如何在这里工作的。我想知道如何使用position:absolute
来制作我的JavaScript引擎,而不是使用position:relative
,以便元素可以堆叠在彼此的顶部等。您可能会发现这很有帮助
你到底有什么问题
Absolute从正常的“文档流”中删除元素,并允许您将其定位到所需的位置
相对位置非常类似于静态,但允许您绝对定位其中的元素
Static遵循正常的文档流。(堆叠)
顺便说一下,我建议您使用JQuery或Prototype之类的库或框架,而不是手工构建。它将为您节省数小时的沮丧和在不同浏览器中的测试
编辑:
既然你做这件事很难…我希望我能帮上忙。
我建议您下载Firefox的firebug插件,如果这是您在Chrome工具下使用或熟悉的Javascript控制台
HTML
第一件事
第二件事
这里没有父/子关系。您的意思是将文档作为边界吗?
在BoundMovement调用的元素offSetParent上,freeMovement不调用findPos。
这是未定义的重新调整,因为文档没有该属性
试着用body标签以外的东西来包装这两段文字
<div id='container'>
<p class="drag bound square">Thing One</p>
<p class="drag square">Thing Two</p>
</div>
第一件事
第二件事
您看过这个jQuery演示吗
使用jQuery可以使JavaScript变得更容易,也可以确保代码在跨浏览器中工作。我认为问题(至少在您的示例中)在于,当您为boundMovement
中的绑定元素调用findPos
函数时,您传递的是它的父元素,而它自己没有父元素。因此在findPos
函数中,这个特定行
if (obj.offsetParent) {
// ...
返回未定义,因为它没有父项。尝试删除if语句,然后重试。我已在上发布了一个解决方案
首先,我将要拖动的项嵌套在边界框中:
<div class="bound">Thing One
<div class="drag square">Thing Two</div>
<div class="drag square">Thing Three</div>
</div>
<style>
.bound {
margin: 100px;
width: 400px;
height: 400px;
position: relative;
}
</style>
请注意,这一行:
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';
var x=event.clientX-dragInfo.posX;
如果(x<0)x=0;
如果(x>dragInfo.maxX)x=dragInfo.maxX;
dragInfo.element.style.left=x+'px';
我强烈建议使用jQuery UI进行拖放。这将为您节省很多时间的跨浏览器测试。@马克,我很感谢您的建议,但这是我学习Javascript的第一周。我这样做是为了帮助我学习语言。在开始使用库作为快捷方式之前,我想先学习这门语言。有时你需要重新发明轮子来理解轮子是如何工作的;从零开始写作的pkudos!我对您的代码做了一些修改,并发布在JSFIDLE上。我很快会为我的答案添加更多的解释。我一定会阅读该网页,谢谢。我的确切问题是,我不知道如何使boundMovement()函数在我的javascript中工作。是的,但正如我在最初的帖子和几条评论中所说:在我真正学习javascript之前,我不希望使用jQuery。不过,我很欣赏这个建议=]很抱歉,我没有看到“元素可以堆叠在彼此的顶部”与位置无关。为了改变它们的堆叠顺序,使用cssz-indexStatic“元素可以堆叠在彼此之上”是一个糟糕的选择。我的意思是,静态元素在页面上垂直向下列出,第一个元素出现在第二个元素的上方/之前。不,它的工作方式与它应该的一样。函数freeMovement()
使用了它,它工作得很好。@Dbz,很有趣。我在freemotation
中没有看到对findPos
的调用。在任何情况下,这里有一个JSFIDLE和您的代码以及一些修改:因此,我在您的修改中添加了一些东西,但并不完全有效:@Dbz,首先一件事:绝对定位元素的偏移父元素是第一个父元素(或父元素的父元素,或…),其位置不是静态的。因此,div不是其偏移父对象,因为默认位置是静态的。在这里看到更多:@ZDYN,哦,孩子,这太令人沮丧了。这是否意味着我的findPos()
函数只能与position:absolute
元素一起工作;P我确实需要一点解释。有很多更改=/@Dbz您必须将要拖动的项放入边界框中。我已经编辑了我的答案,包括更多的解释。如果您有问题,请再次评论。@Mark,首先,感谢您解释为什么我不需要findPos()
,这让我发疯了。第二,有必要设置一个.bound
框是一个好主意吗?这似乎是一个限制,而不是一个特性(尽管它显然有它的优点)。我将查找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';