Flyingis

Talking and thinking freely !
Flying in the world of GIS !
随笔 - 156, 文章 - 16, 评论 - 589, 引用 - 0
数据加载中……

[翻译] 如何在 JavaScript 中实现拖放(中)

    译者: Flyingis 

    上一篇文章
介绍了移动页面元素所涉及到的捕获鼠标移动和鼠标点击的相关问题,本段文章将介绍如何移动和放置页面元素。

    移动元素

    我们现在已经知道如何捕获鼠标移动和点击。接下来需要做的就是移动任何我们想拖动的元素。首先,将一个元素准确移动到页面上我们想要的位置,该元素样式表的position值必须为absolute,这意味着你可以设置它的style.top或style.left,测量值相对于页面的左上角,因为我们所有的鼠标移动都是相对于页面左上角的,通常都是这样。

    一旦我们设置了item.style.position='absolute',接下来就需要改变该元素top和left的位置,使它移动!

document.onmousemove  =  mouseMove;
document.onmouseup   
=
 mouseUp;

var  dragObject   =   null
;
var  mouseOffset  =   null
;

function  getMouseOffset(target, ev) 
{
  ev 
=  ev  ||
 window.event;

  
var  docPos  =
 getPosition(target);
  
var  mousePos  =
 mouseCoords(ev);

   
return   {x:mousePos.x  -  docPos.x, y:mousePos.y  -  docPos.y}
;
}


function  getPosition(e)  {
  
var  left  =   0
;
  
var  top   =   0
;

  
while  (e.offsetParent)
{
    left 
+=
 e.offsetLeft;
    top 
+=
 e.offsetTop;
    e 
=
 e.offsetParent;
  }


  left 
+=  e.offsetLeft;
  top 
+=
 e.offsetTop;

  
return   {x:left, y:top}
;
}


function  mouseMove(ev)  {
  ev 
=  ev  ||
 window.event;
  
var  mousePos  =
 mouseCoords(ev);

  
if  (dragObject) 
{
    dragObject.style.position 
=
 'absolute';
    dragObject.style.top 
=  mousePos.y  -
 mouseOffset.y;
    dragObject.style.left 
=  mousePos.x  -
 mouseOffset.x;
    
return   false
;
  }

}


function  mouseUp()  {
  dragObject 
=   null
;
}


function  makeDraggable(item)  {
  
if  ( ! item)  return
;
  item.onmousedown 
=   function (ev) 
{
    dragObject  
=   this
;
    mouseOffset 
=  getMouseOffset( this
, ev);
    
return   false
;
  }

}

    你会注意到这些代码是以我们前面的例子为基础的(参考上篇文章),将它们放置在一起,你将能够随意的去移动元素。

    当我们点击一个元素时,存储了另外的一个变量,mouseOffset。mouseOffset简单的包含了我们点击元素的位置信息。如果我们有一张20*20px的图像,然后点击图像的中间,mouseOffset应该是{x:10, y:10}。如果我们点击图像的左上角,mouseOffset应为{x:0, y:0}。我们在鼠标移动后的位置信息中用到它。如果我们没有存储这个值,不论你点击元素的哪一个位置,元素相对于鼠标的位置都将会是相同的。

    mouseOffset函数用到了另外一个函数getPosition。getPosition目的是返回元素相对于documemt文档的坐标位置。如果我们简单的去读取item.offsetLeft或item.style.left,得到的将是元素相对于它父元素的位置,而不是document文档的。在我们的脚本中,所有的元素都是相对于document文档的,因此需要这样做。

    要完成获取元素相对于document文档位置的工作,getPosition从它自身的父级开始,循环获取它的left和top的值并累加,这样我们就得到了我们想要的元素距文档顶部和左侧的累计值。

    当我们获取了这条信息并移动鼠标的时候,mouseMove开始运行。首先我们需要保证item.style.position值为absolute,接着,我们将元素移动到任何一个地方,鼠标位置都会减去我们之前记录的鼠标相对于元素的偏移量。当鼠标释放时,dragObject将被设置为null,并且mouseMove函数不再做任何事情。

    放置元素

    我们前面的例子已经处理了这个问题,仅仅是拖动一个元素,然后将它放下。然后,在我们放下元素的时候通常还有其他的目的,我们以拖动元素到垃圾回收站为例,或我们可能想让该元素和页面中某个特定的区域对齐。

    不幸的是我们在这里进入了一个相对主要的问题。因为我们正在移动的元素总是直接处于我们的鼠标下,而不可能去引发mouseover、mousedown、mouseup或鼠标对页面中其他元素的操作。如果你移动一个元素到垃圾回收站,你的鼠标会一直在移动元素的上方,而不是垃圾回收站。

    那么我们该如何处理这个问题呢?这里有几种解决方案。在前面所提到的mouseOffset的目的是保证元素总是在鼠标下方正确的位置,如果你忽视了这点,然后总是使得元素在鼠标的右下方,你的鼠标将不会被你正在拖动的元素所隐藏,我们也不会碰到问题。但事实上往往不会这样,为了美观我们通常要保持元素在鼠标的下方。

    另外一种选择是不移动你正在拖动的元素,你可以改变鼠标样式,来告诉使用者你正在拖动一个元素,直到你将它放置到某个地方。这解决了我们的问题,但是带来了和前面一种方案面临的同样问题:美观。

    我们最后的一种解决方案既不影响你正在移动的元素,也不影响移动终点位置上的元素(例如垃圾回收站)。不幸的是,这比前面两种解决方案的难度更大。我们将要做的是获得一组我们要放置的目标,当鼠标释放时,我们手工检查当前鼠标相对于每个目标的位置,看鼠标是否释放在这个目标中某一个目标的位置上,如果是的,我们就知道我们已经将元素放置在我们的目标上了。

/*
All code from the previous example is needed with the exception
of the mouseUp function which is replaced below
*/


var  dropTargets  =  [];

function  addDropTarget(dropTarget) 
{
  dropTargets.push(dropTarget);
}


function  mouseUp(ev)  {
  ev 
=  ev  ||
 window.event;
  
var  mousePos  =
 mouseCoords(ev);

  
for  ( var  i = 0 ; i < dropTargets.length; i ++
{
    
var  curTarget  =
 dropTargets[i];
    
var  targPos  =
 getPosition(curTarget);
    
var  targWidth  =
 parseInt(curTarget.offsetWidth);
    
var  targHeight  =
 parseInt(curTarget.offsetHeight);

    
if
 (
      (mousePos.x 
>  targPos.x)  &&
 
      (mousePos.x 
<  (targPos.x  +  targWidth))  &&
 
      (mousePos.y 
>  targPos.y)  &&
 
      (mousePos.y 
<  (targPos.y  +  targHeight))) 
{
      
//  dragObject was dropped onto curTarget!

      }

  }


  dragObject   
=   null ;
}

    这个例子中当鼠标释放时,我们循环每个可能放置元素的目标,如果鼠标指针在目标上,我们则拥有了一个放置元素的事件,通过鼠标横坐标大于目标元素左侧横坐标(mousePos.x>targPos.x),小于目标元素右侧横坐标(mousePos.x<(targPos.x+targWidth))来判定,对于Y坐标我们做同样的判断。如果所有的这些值都返回true,那么我们的鼠标就是在目标元素的范围内。

    原文链接:http://www.webreference.com/programming/javascript/mk/column2/2.html

    另外两篇:[翻译] 如何在 JavaScript 中实现拖放(上)   [翻译] 如何在 JavaScript 中实现拖放(下)

posted on 2006-10-13 14:53 Flyingis 阅读(5263) 评论(2)  编辑  收藏 所属分类: Web 客户端技术

评论

# re: [翻译] 如何在 JavaScript 中实现拖放(中)  回复  更多评论   

不错,收藏了。。呵呵
2006-10-13 20:56 | Vista

# re: [翻译] 如何在 JavaScript 中实现拖放(中)  回复  更多评论   

增开7群,号码 30440732
8群 30756649
9群 30178567
10群 28694497

我们的qq群:15096318 学习程序的都可以来
2006-10-18 15:45 | 123bingbing

只有注册用户登录后才能发表评论。


网站导航: