我在JavaScript中制作拖放引擎,我不知道如何设置dragObj的正确位置,因为它会根据父元素的定位类型而改变(dragObj是否也会根据其父元素的变化而改变) “父元素”等。?)。
所以,我的dragObj看起来像这样:
function makeObj(event) {
var obj = new Object();
var e = event.target;
obj.element = e;
obj.boundElement = null;
while(e = e.parentNode) {
if(~e.className.search(/bound/)) { //if(/bound/.test(e.className)) {
obj.boundElement = e;
break;
}
}
if(obj.boundElement == null)
obj.boundElement = document.body;
// I would like to find the correct minimum bounds with findPos(); however, I need
// findPos() to work with every type of positioning (absolute, relatice, ect.)
//var elemPos = findPos(obj.boundElement);
//obj.minBoundX = elemPos.x;
//obj.minBoundY = elemPos.y;
obj.minBoundX = obj.boundElement.offsetLeft + obj.boundElement.offsetWidth - obj.element.offsetWidth;
obj.minBoundY = obj.boundElement.offsetTop + obj.boundElement.offsetHeight - obj.element.offsetHeight;
obj.maxBoundX = obj.boundElement.offsetLeft;
obj.maxBoundY = obj.boundElement.offsetTop;
setHelperBoxPos(obj);
obj.posX = event.clientX - obj.element.offsetLeft;
obj.posY = event.clientY - obj.element.offsetTop;
return obj;
}
所以,当我做一个dragObj时,我也设置了它的“位置”和它的bounding element
。在我设置.minBoundX
和.minBoundY
属性之前的评论部分中,我解释了如何设置它们;但是,它不起作用,因为findPos()函数不起作用。
这是findPos()函数:
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 };
}
}
我相信如果bounding element
设置position: absolute;
,此功能有效,但我希望用户能够设置其定位类型。此外,bounding element
由.bound
类设置,dragObj由.drag
类设置。
这是HTML:
<div id="min" class="helper-box" style="border: 1px solid blue;"></div>
<div id="max" class="helper-box" style="border: 1px solid red;"></div>
<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>
这是CSS:
@charset "utf-8";
/* CSS Document */
* {
padding: 0px;
margin: 0px;
}
body {
background-color:#DFDFDF;
}
.drag {
position: absolute;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.bound {
;
}
.square {
width: 100px;
height: 100px;
background: #1047A9;
cursor:move;
border-radius: 25px;
-moz-border-radius: 25px;
}
#center {
width: 500px;
margin: auto;
margin-top: 50px;
background-color: #29477F;
color: #E8E8E8;
text-align: center;
border-radius: 25px;
-moz-border-radius: 25px;
}
#box {
background-color: #009EBE;
height: 275px;
border-radius: 0 0 25px 25px;
-moz-border-radius: 0 0 25px 25px;
opacity: 1.0;
}
.helper-box {
position: absolute;
width: 5px;
height: 5px;
}
这是整个引擎:
// JavaScript Document
var dragObj;
document.addEventListener("mousedown", down, false);
function down(event) {
if(~event.target.className.search(/drag/)) {
dragObj = makeObj(event);
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(dragObj.maxBoundX, Math.min(dragObj.minBoundX, event.clientX - dragObj.posX)) + "px";
dragObj.element.style.top = Math.max(dragObj.maxBoundY, Math.min(dragObj.minBoundY, event.clientY - dragObj.posY)) + "px";
}
function drop() {
dragObj.element.style.zIndex="1";
document.removeEventListener("mousemove", freeMovement, false);
document.removeEventListener("mouseup", drop, false);
//alert("DEBUG_DROP");
}
function makeObj(event) {
var obj = new Object();
var e = event.target;
obj.element = e;
obj.boundElement = null;
while(e = e.parentNode) {
if(~e.className.search(/bound/)) { //if(/bound/.test(e.className)) {
obj.boundElement = e;
break;
}
}
if(obj.boundElement == null)
obj.boundElement = document.body;
// I would like to find the correct minimum bounds with findPos(); however, I need
// findPos() to work with every type of positioning (absolute, relatice, ect.)
//var elemPos = findPos(obj.boundElement);
//obj.minBoundX = elemPos.x;
//obj.minBoundY = elemPos.y;
obj.minBoundX = obj.boundElement.offsetLeft + obj.boundElement.offsetWidth - obj.element.offsetWidth;
obj.minBoundY = obj.boundElement.offsetTop + obj.boundElement.offsetHeight - obj.element.offsetHeight;
obj.maxBoundX = obj.boundElement.offsetLeft;
obj.maxBoundY = obj.boundElement.offsetTop;
setHelperBoxPos(obj);
obj.posX = event.clientX - obj.element.offsetLeft;
obj.posY = event.clientY - obj.element.offsetTop;
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 };
}
}
function setHelperBoxPos(obj) {
var minBox = document.getElementById('min');
minBox.style.left = obj.minBoundX + 'px';
minBox.style.top = obj.minBoundY + 'px';
var maxBox = document.getElementById('max');
maxBox.style.left = obj.maxBoundX + 'px';
maxBox.style.top = obj.maxBoundY + 'px';
}
为方便起见,我也做了一个jsfiddle:http://jsfiddle.net/2XGhK/
那么,我如何创建一个允许不同类型定位的findPos()函数。我是否需要创建另一个findPos()函数以允许dragObj成为任何类型的定位?
重要请不要建议使用图书馆(除非您建议查看它们如何处理定位的提示)。原因是我只是在学习语言并且构建有助于我的东西做到这一点。在我理解这门语言之前学习图书馆有什么意义?
最重要的是,我非常感谢你的帮助。谢谢。
答案 0 :(得分:6)
在开发Javascript时,jQuery确实是你最好的朋友,因为它简化了许多这些(可能令人讨厌的)任务。尽管如此,我完全挖掘了没有他们的学习欲望;这是一种变得精通的好方法。
看一下jQuery的position
和offset
的文档和实现,希望这会让你对起点有一个好主意。
文档:
http://api.jquery.com/position/
来源:
答案 1 :(得分:2)
我不知道这是否正是你所需要的,但是使用javascript实现拖放需要付出很多努力和测试,特别是当你处理父子拖动时。
试试这个:
http://interface.eyecon.ro/demos/drag.html
也许您可以阅读其源代码并使用它来满足您的需求。
答案 2 :(得分:1)
简单地将拖动对象的位置设为绝对 -
obj.element = e;
obj.element.style.position = "absolute";
obj.boundElement = null;
不过,谢谢你使用jsfiddle,它有所帮助。
答案 3 :(得分:0)
我是JavaScript的初学者。我发现你的问题非常有趣,并想到谷歌搜索它。我找到了这两个可能对您有用的链接:
http://www.codingforums.com/archive/index.php/t-84055.html
http://www.codeproject.com/KB/scripting/DragDrop_Part-2.aspx
答案 4 :(得分:0)
此代码片段有用吗?
var position = {};
var dragObj = "";
function initDrag(e){
e = e || window.event;
position.objLeft = parseInt(dragObj.style.left);
position.objTop = parseInt(dragObj.style.top);
if( isNaN(position.objLeft) )
position.objLeft = 0;
if( isNaN(position.objTop) )
position.objTop = 0;
position.startX = e.clientX;
position.startY = e.clientY;
if( document.addEventListener )
{
e.preventDefault();
dragObj.addEventListener('mousemove',startDrag,false);
dragObj.addEventListener('mouseup',stopDrag,false);
dragObj.addEventListener('mouseout',stopDrag,false);
}
else
{
dragObj.attachEvent('onmousemove',startDrag);
dragObj.attachEvent('onmouseup',stopDrag);
dragObj.attachEvent('onmouseout',stopDrag);
}
}
function startDrag(e){
e = e || window.event;
dragObj.style.left = position.objLeft+e.clientX-position.startX;
dragObj.style.top = position.objTop+e.clientY-position.startY;
return false;
}
答案 5 :(得分:0)
实际上,在查找元素位置时,使用其offsetLeft(/Top)
。并且每个元素都有offsetParent
来自该位置的起源。当你拖动一个元素时,最好根据整个文档(读取)知道它的位置,这样你就可以获得更精确的点。因此,要找到elementes位置,您必须创建以下函数:
function findPos(elm) {
var testElm = elm, pos = {x:0, y:0};
while( !!testElm && testElm.tagName.toLowerCase() !== "body" ) {
pos.x += testElm.offsetLeft;
pos.y += testElm.offsetTop;
// important to use offsetParent instead of just parentNode,
// as offsetParent will be where the element gets its offset from.
// And that is not necesarily it parentNode!
testElm = testElm.offsetParent;
}
return pos;
}
但我同意其他一些观点,jQuery DO简化了很多繁琐的计算。但我真的认为在使用API之前最好先了解JS,因为它可以让你了解JS的真正含义。
PS。不要为每个mousemove
事件调用此方法,因为它会影响性能。 Intead将值保存在元素(<your node>["startoffset"] = findPos(<your node>)
)上,然后在mousemove脚本中使用它来查找其新位置。实际上,最好在mousedown
上保存尽可能多的值,因为mousemove
将被称为ALOT,因此应尽可能少地进行计算/遍历。
答案 6 :(得分:0)
最简单的解决方案:
将元素设置为visibility:hidden
。克隆元素,将克隆设置为position:absolute
,执行拖动。拖动停止后(即用户释放了鼠标左键),将克隆替换为原始元素。
这允许您在可拖动操作期间将元素保持在流中。这样,如果元素无法在位置y中删除(例如),则可以让帮助程序快照回原始位置。