В настоящее время я занимаюсь созданием дизайнера веб-сайтов, и одна из основных функций - возможность перетаскивать и изменять элементы. Я работал над этой функцией в течение нескольких дней и несколько раз отклеивался. Самое важное замечание об этой системе перетаскивания - то, что перетаскиваемый элемент может быть отброшен в любом месте в главном контейнере, и он защелкнется на месте, поэтому не будет абсолютно позиционированных элементов, в противном случае элемент не защелкнется на месте.
Итак, сначала я начал с создания перетаскиваемого основного бита, куда вы можете перетаскивать элемент, затем, когда вы отбрасываете элемент, я использую document.elementFromPoint()
чтобы получить элемент, в котором находится позиция курсора (примечание: мне нужно скрыть перетаскиваемый элемент, в противном случае он вернет это).
Теперь у меня есть элемент, ближайший к курсору, основная проблема в том, чтобы выяснить, куда нужно перетаскивать перетаскиваемый элемент по отношению к этому элементу, потому что есть 4 опции append - prepend - insertBefore - insertAfter
. Мне удалось получить append - prepend & insertBefore
работающий, но он недостаточно надежный, потому что все, что я собираюсь, это использовать высоту и смещение цели, чтобы определить, append or prepend
и я увеличиваю параметр Y
в getFromPoint
чтобы увидеть, если я нажмите другой элемент на коротком расстоянии, чтобы определить insertBefore
. Вот код, который у меня есть.
box.addEventListener('mouseup', function (e) {
if (!dragging) return;
dragging = false;
var thisEl = this; // the drag-able element
// Hide
this.style.display = 'none'; // hide the element so we can get
// document.elementFromPoint
var el = document.elementFromPoint(e.pageX, e.pageY), // target
elH = el.offsetHeight, // height of target
elT = el.offsetTop; // offset of target
for (var i = 0; i < 15; i++) { // This is a weird part see the reference at the bottom
var newEl = document.elementFromPoint(e.pageX, e.pageY + i);
if (newEl !== el) {
this.style.display = 'block';
this.style.position = 'static';
return newEl.parentNode.insertBefore(thisEl, newEl);
}
}
if (e.pageY < elT + (elH / 2)) { // if the pageY is less than the target offset + half of the height, that how I am calculating prepend
el.appendChild(this);
el.insertBefore(this, el.firstChild);
} else {
el.appendChild(this); // else append;
}
this.style.display = 'block';
this.style.position = 'static'; // Snap back in with 'static'
});
Это всего лишь мое событие mouseup
которое выполняет всю работу. другие события просто делают элемент перетаскиваемым, не очень важным.
Вот скрипка
http://jsfiddle.net/mLX5A/2/
Так что, если это не задать вопрос, то здесь короткая версия.
Мой перетаскиваемый элемент должен быть в любом месте и быть привязанным к нему. Что является лучшим способом сделать это, потому что способ, которым я сделал это в скрипке, определенно не хорош. Как я могу определить, куда должен попасть элемент относительно цели при наведении mouseup
.
Ссылка на странный раздел.
Вот как это работает (предупреждение, это не хорошо). Когда я получаю целевой элемент с помощью elementFromPoint
я тогда создаю цикл, который будет elementFromPoint
цикл 15 раз и увеличивать значение Y
которое входит в elementFromPoint
поэтому в основном elementFromPoint
перемещается вниз на 15px
и если он попадает в новый элемент в пределах этого короткого пространства, я предполагаю что вы хотите вставить элемент перед целью.
Я более чем счастлив получить ответы, которые не имеют ничего общего с этим кодом, поскольку это пойдет на пользу и другим пользователям.
Я хотел бы отметить, что контейнер, который будет иметь возможность перетаскивания, является основной частью конструктора. Поэтому я не могу выбирать все абсолютно позиционированные элементы, и мне не очень хорошая идея размещать элемент в каждом возможном месте, чтобы я мог определить, куда должен перемещаться перетаскиваемый элемент, потому что все, что находится в этот контейнер будет качественным результатом без лишнего содержимого.
Я также хотел бы отметить, что мое приложение не поддерживает и не будет поддерживать старые браузеры, т.е. IE6, IE7, IE8, IE9.