65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Javascript 进行拖放

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.64/5 (7投票s)

2007年8月30日

3分钟阅读

viewsIcon

60286

downloadIcon

641

本文介绍了一种在 HTML 页面中拖放元素的方法

引言

随着人们推动以用户为中心的发展,拖放功能只是在强调以用户为中心开发的网页中常见的功能之一。本文讨论了一种实现这种功能的方法,同时考虑到浏览器兼容性的问题。

使用代码

我为此使用了面向对象的方法(当然也可以在没有面向对象的情况下完成)。负责拖放的主要类是 Drag。我们只需要调用 Init() 函数即可启动它。它的作用是确定浏览器的类型并设置相应的变量。

说到拖放,我首先想到的是

  1. 鼠标按键按下,
  2. 鼠标移动,
  3. 鼠标按键抬起。

我们将通过检索鼠标的当前 (x,y) 坐标并设置元素的 left,top 属性来控制“元素”的位置。

类声明

        function Drag()
        {
            this.id=""
            this.beginDrag=""
            this.browserType=""
            this.eventObj=""
            this.bodyID=""
                        
            Drag.prototype.SetBrowserType=SetBrowserType
            Drag.prototype.Init=InitDragClass
            Drag.prototype.GetBrowserType=GetBrowserType
            Drag.prototype.BeginDrag=BeginDrag
            Drag.prototype.GetDragState=GetDragState
            Drag.prototype.EndDrag=EndDrag
            Drag.prototype.GetCurrentCoOrdinates=GetCurrentCoOrdinates        
            Drag.prototype.Move=Move
            Drag.prototype.SetId=SetId
            Drag.prototype.GetId=GetId
            Drag.prototype.SetEventObj=SetEventObj
            Drag.prototype.GetEventObj=GetEventObj
            Drag.prototype.RemoveChild=RemoveChild
            
        }
        
        function Position()
        {
                this.x=""
                this.y=""
        }
        
    

不要被函数数量吓倒,它们中的大多数只是 getter 和 setter,而且不言自明。以下是一些需要解释的:

  • this.id -> 这将保存我们要拖动的“元素”的 id。
  • this.eventObj -> 考虑到跨浏览器差异,我使用 'eventObj' 来表示不同浏览器的 'event' 对象。
  • this.beginDrag -> 这是一个标志,用于指示拖动操作的状态。
        function Move(obj,pos)
        {
                obj.style.position="absolute"
                obj.style.zIndex="999"
                obj.style.left=pos.x+"px"
                obj.style.top=pos.y+"px"                
        }
        
        function GetCurrentCoOrdinates()
        {
            var pos=new Position()    
            
            if(this.GetBrowserType()=="MOZILLA")
            {
                pos.x=(typeof this.GetEventObj().pageX =="undefined") ? 0 : this.GetEventObj().pageX 
                pos.y=(typeof this.GetEventObj().pageY =="undefined") ? 0 : this.GetEventObj().pageY
            }
            else if(this.GetBrowserType()=="IE")
            {
                pos.x=(this.GetEventObj().x < 0 || typeof this.GetEventObj().x=="undefined")? 0 : this.GetEventObj().x
                pos.y=(this.GetEventObj().y < 0 || typeof this.GetEventObj().y=="undefined")? 0 : this.GetEventObj().y
            }
            
            return pos
        }
        
    function RemoveChild() 
    { 
        try 
        { 
            var obj=document.getElementById(this.GetId()) 
            var objParent=obj.offsetParent 
            var objBody=document.getElementById(this.bodyID) 
            objParent.removeChild(obj) 
            objBody.appendChild(obj) 
        } 
        catch(err) 
        { 
        } 
    }    

如类声明所示,Move() 负责实际移动相关元素。GetCurrentCoOrdinates() 如其名称所示,返回 Position 对象。我不会解释其余函数的实现,因为它们的名称暗示了它们的功能,并且它们包含在示例源代码中。

RemoveChild 是一个错误修复。在此之前,元素受其父元素的区域限制(它们无法超出其父元素的区域向左移动)。为了解决这个问题,我从父元素中删除目标元素,并将其附加到页面的 body 中。body 拥有整个页面区域。仍然存在旧的限制,但由于 body 是页面,我们不会遇到这种限制。并且由于我们将其附加到 body,因此我们需要给 body 一个 id。我在调用 Init() 时设置了 id。

我们需要处理 onmousedown、onmousemove、onmouseup 事件,我们需要明确指定我们对此感兴趣。

        document.onmousemove=function(e) //e for Mozilla Firefox
        {
                HandleMouseMove(e)
        }
        
        document.onmouseup=function(e)
        {
                if(dragObj.GetId()!=null && dragObj.beginDrag==true)
                {
                    HandleMouseUp(dragObj.GetId())
                }
        }
    

注意:Internet Explorer 中似乎存在一个错误,因为它没有在“element”的声明中调用“onmouseup”事件,所以我不得不明确地写下来。为了处理鼠标按下事件,我使用了函数 HandleMouseDown(id)。

        function HandleMouseUp(id)
        {
            dragObj.EndDrag() //set the beginDrag flag to false
            dragObj.SetId("") //clear the id, since we stopped dragging the 'element'
        }
        
        function HandleMouseDown(id)
        {
                
                dragObj.BeginDrag() //set the beginDrag flag to true
                dragObj.SetId(id)   //set the id to denote the 'element' we are interested to drag.
        }
        
        function HandleMouseMove(eventObj) //this would accept the parameter for event, which is a local object for Firefox.
        {                                  //Since it is a global object in Internet Explorer, we don't have to worry about it.
        
                if(typeof eventObj!="undefined")  //this means browser is Firefox
                {
            
                    if(dragObj.GetId()!=null && dragObj.beginDrag==true)
                    {                            
                        dragObj.SetEventObj(eventObj)
                        dragObj.RemoveChild()
                        dragObj.Move(document.getElementById(dragObj.GetId()),dragObj.GetCurrentCoOrdinates())
                    }    
                }
                else    //this means browser is Internet Explorer
                {
                    if(dragObj.GetId()!=null && dragObj.beginDrag==true)
                    {                            
                            dragObj.SetEventObj(event)
                            dragObj.RemoveChild()
                            dragObj.Move(document.getElementById(dragObj.GetId()),dragObj.GetCurrentCoOrdinates())
                    }
                }
                                
        }
    

当拖动结束时,zIndex 将被设置回 null。设置 zIndex 会将相关元素置于前景。最后,您需要在声明元素时添加这段代码

     onmousedown="javascript:HandleMouseDown(this.id)" onmouseup="javascript:HandleMouseUp(this.id)" onmousemove="HandleMouseMove(this.id)"

我们现在准备好拖动了。我附上了一个示例供参考。

历史

v 1.0 已添加

v 1.1 错误修复,元素现在不受其父元素区域的限制。

© . All rights reserved.