定位如何在HTML / CSS中工作?

时间:2011-02-26 04:16:48

标签: 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);

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}},以便元素可以堆叠在彼此之上等。

4 个答案:

答案 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更容易,并且还将确保您的代码跨浏览器工作。