Подтвердить что ты не робот

Как я могу установить "ограничительную" область для моего объекта с возможностью перетаскивания в javascript?

Я создаю движок Drag and Drop JavaScript. Я узнал, как установить ограничивающий прямоугольник в качестве родительского элемента. Однако теперь я хочу установить ограничительную рамку для любого родителя любого родителя или как целую страницу (без ограничений).

Сейчас Javascript Engine выглядит так:

// JavaScript Document

var dragObj;

document.addEventListener("mousedown", down, false);

function down(event) {
    if(~event.target.className.search(/drag/)) {
        dragObj = makeObj(event.target);
        dragObj.element.style.zIndex="100";
        document.addEventListener("mousemove", freeMovement, false);
    }
}

function freeMovement(event) {

    if (typeof(dragObj.element.mouseup) == "undefined")
        document.addEventListener("mouseup", drop, false);
    //Prevents redundantly adding the same event handler repeatedly

    dragObj.element.style.left = Math.max(0, Math.min(event.clientX - dragObj.posX, dragObj.boundX)) + "px";
    dragObj.element.style.top = Math.max(0, Math.min(event.clientY - dragObj.posY, dragObj.boundY)) + "px";
}

function drop() {
    dragObj.element.style.zIndex="1";

    document.removeEventListener("mousemove", freeMovement, false);
    document.removeEventListener("mouseup", drop, false);
    //alert("DEBUG_DROP");
}

function makeBoundlessObj(e) {
    var obj = new Object();
    obj.element = e;

    obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
    obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

    obj.posX = event.clientX - e.offsetLeft;
    obj.posY = event.clientY - e.offsetTop;

    return obj;
}

function makeObj(e) {
    obj = new Object();
    obj.element = e;

    obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
    obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

    obj.posX = event.clientX - e.offsetLeft;
    obj.posY = event.clientY - e.offsetTop;

    var curleft = curtop = 0;
    if (e.offsetParent) {
        do {
            curleft += e.offsetLeft;
            curtop += e.offsetTop;
            //alert(e.id + ":" + e.innerHTML);
            if(~e.className.search(/bound/)) {
                obj.boundX = curleft - obj.element.offsetLeft;
                obj.boundY = curtop - obj.element.offsetTop;
                return obj;
            }

        } while (e = e.offsetParent);
    }

    return obj;
}

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 */


* {
    padding: 0px;
    margin: 0px;
}

.drag {
    position: absolute;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}

.bound {
    position: relative;
}

.square {
    width: 100px;
    height: 100px;
    background: red;
    cursor:move;
}

#center {
    width: 500px;
    height: 300px;
    margin: auto;
    margin-top: 50px;
    background-color:#ccc;
    text-align: center;
    border-radius: 25px;
    -moz-border-radius: 25px;
}

#box {
    background-color: #FF3;
    height: 278px;
    border-radius: 0 0 25px 25px;
    -moz-border-radius: 0 0 25px 25px;
    opacity: 0.5;
}

И мой HTML довольно чистый:

<div id="center">
    <h1>Hello World! <hr /></h1>
    <div id="box" class="bound">
        <p class="drag square"> One </p>
        <p class="drag square"> Two </p>
    </div>
</div>

Я попытался сделать правильные функции несколько раз. Я дам тот, который я создал, который не работает, и я расскажу, почему:

  • Если у него нет границ, я устанавливаю ограничения по умолчанию в качестве родительского элемента (потому что я не знаю, как устанавливать границы как целую страницу)

  • Если один из родительских элементов IS привязан, то я не задаю правильные привязки (опять же, я не знаю, как)

О, и я устанавливаю границы при создании объекта drag_object.

Функция создания JavaScript:

function makeObj(e) {
    var obj = new Object();
    obj.element = e;

    obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
    obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

    obj.posX = event.clientX - e.offsetLeft;
    obj.posY = event.clientY - e.offsetTop;

    var curleft = curtop = 0;
    if (e.offsetParent) {
        do {
            curleft += e.offsetLeft;
            curtop += e.offsetTop;
            //alert(e.id + ":" + e.innerHTML);
            if(~e.className.search(/bound/)) {
                obj.boundX = curleft - obj.element.offsetLeft;
                obj.boundY = curtop - obj.element.offsetTop;
                return obj;
            }

        } while (e = e.offsetParent);
    }

    return obj;
}

Какова правильная математика для установки ограничительной рамки и почему? Могу ли я избавиться от position: relative в классе .bound? Могу ли я сделать класс .drag не position: absolute? Я знаю, что все эти вещи, вероятно, сильно повлияют на то, как записывается ограничивающая функция. Если бы я имел выбор между тем, чтобы класс .drag или класс .bound не нуждался в определенном типе position, я бы выбрал, чтобы класс .bound был настроен на любой тип позиционирование.

Спасибо всем за чтение и помощь! Это очень много значит для меня; Я полный рабочий день (посадку) школьника с очень небольшим свободным временем =/

EDIT:

Я должен отметить, что я нахожусь на десятый день обучения Javascript или пятнадцатого часа в зависимости от того, как вы на это смотрите, и я хотел бы изучить этот язык, прежде чем я начну использовать библиотеки, такие как jQuery. Этот движок - это академическое упражнение, которое я сделал для себя ради знания и изучения языка. =]

4b9b3361

Ответ 1

Первое, что я заметил, это то, что у вас не было минимальной границы. Это необходимо для обеспечения соблюдения верхней и нижней границ.

Какова правильная математика для установки ограничительной рамки и почему?

Прежде всего, нужно, чтобы dragObj учитывал обе границы (относится к position: absolute):

// parentNode is our bounding box
// the minimum boundary is based on the top left corner of our container
obj.minBoundX = e.parentNode.offsetLeft;
obj.minBoundY = e.parentNode.offsetTop;

// the maximum is the bottom right corner of the container
// or.. the top left (x,y) + the height and width (h,y) - the size of the square
obj.maxBoundX = obj.minBoundX + e.parentNode.offsetWidth - e.offsetWidth;
obj.maxBoundY = obj.minBoundY + e.parentNode.offsetHeight - e.offsetHeight;

Выполнение границ - это простое обновление до freeMovement:

dragObj.element.style.left = Math.max(dragObj.minBoundX, Math.min(event.clientX - dragObj.posX, dragObj.maxBoundX)) + "px";
dragObj.element.style.top = Math.max(dragObj.minBoundY, Math.min(event.clientY - dragObj.posY, dragObj.maxBoundY)) + "px";

Можно ли избавиться от позиции: относительная в классе .bound? Да.

Могу ли я сделать класс .drag не position: absolute? Ага. Вы просто хотите изменить свои позиции, чтобы быть относительными, и ваши расчеты для учета этого. Например, ваша минимальная граница теперь будет равна 0.

// parentNode is our bounding box
// the minimum boundary is based on the top left corner of our container
obj.minBoundX = 0;
obj.minBoundY = 0;

Вот JSFiddle для версии position:absolute: http://jsfiddle.net/feWcQ/ (работает с Firefox 4). Я также добавил две крошечные коробки, которые показывают ваши границы. Надеюсь, мой ответ поможет вам!

Ответ 2

Итак, прежде чем я удалю, я настоятельно рекомендую книгу от OReilly "Полное руководство по JavaScript". Я узнал тонну там (и впоследствии забыл, когда мне не приходилось использовать его каждый день).

Таким образом, существует много способов скрыть эту кошку, но мне самой сложной является получение позиций соответствующих вещей кросс-браузерным способом без использования библиотеки. Я на самом деле не помню точный синтаксис (поэтому я не буду пытаться), но в основном вам нужно будет найти позицию ограничительной рамки и позицию перемещенного элемента с помощью этой формулы: http://blog.firetree.net/2005/07/04/javascript-find-position/, а затем учитывайте ширину элемента и т.д., чтобы оставаться внутри полей.