改善JavaScript拖动效果

时间:2014-12-12 19:02:25

标签: javascript drag

我设法实现了一个简单的JavaScript拖动效果,在网页内创建“面板窗口”,我可以从任意角落或位置拖动对象。我只使用onmousedown(表示可能的拖动),onmousemove(执行拖动)和onmouseup(停止拖动)事件。

除非我将对象拖得太靠近边缘并且以正常速度移动鼠标,否则它的效果很好。当我将鼠标移动到对象外部的区域时,拖动将失败,直到我再次移动到对象的区域,我必须单击该对象以停止拖动它。

这就像鼠标太快,但显然它不会在本机应用程序窗口中发生,因为它们可以更好地实现。

我可以将哪些检查添加到当前代码中,以便它不会失败多少?它似乎通过某种方式处理onmouseout事件来支持一点点这个问题,但是当它发生时,窗口会摇动以将鼠标指针返回到对象区域,并且看起来不太好。

JavaScript Simple Dragging Effect

    <!doctype html>
    <html>
     <head>
      <title>JavaScript Simple Dragging Effect</title>

      <style type="text/css">
       .moveableRect {
        position:absolute;
        width:320px;
        height:200px;
        background-color:rgba(254, 220, 186, 0.8);
       }
      </style>
     </head>

     <body bgcolor="#abcdef">
      <span id="span0000" class="moveableRect"><b>Drag Me<hr /></b></span>

      <textarea id="txt" cols="40" rows="12"></textarea>
     <script>
      //Custom variable to indicate that we
      //must drag the SPAN:
      ///
       document.getElementById("span0000").myDragFlag = false;


      //When we click and hold the mouse down,
      //we must activate the dragging process:
      ///
       document.getElementById("span0000").onmousedown = function(e)
       {
        if(e.button==0)
        {
         //This is the part of the trick that allows us
         //to drag the object from any starting position
         //that we click on it:
         ///
          this.startX=(e.pageX-this.offsetLeft);
          this.startY=(e.pageY-this.offsetTop);

         //This flag indicates that we must drag
         //when moving the mouse while the button is pressed:
         ///
          this.myDragFlag=true;
        }
       };


      //When we move the mouse, we must follow
      //the mouse cursor around:
      ///
       document.getElementById("span0000").onmousemove = function(e)
       {
        var bcr=this.getBoundingClientRect();

        if(this.myDragFlag)
        {
         //When we start dragging (moving the mouse
         //while the mouse button is pressed)
         //we will perform the effect of dragging from any
         //initial position in the rectangle:
         ///
          this.style.left = (e.pageX-this.startX)+"px";
          this.style.top  = (e.pageY-this.startY)+"px";


          document.getElementById("txt").value=
          "getBoundingClientRect.left="+bcr.left+"\n"+
          "getBoundingClientRect.top="+bcr.top+"\n"+
          "getBoundingClientRect.width="+bcr.width+"\n"+
          "getBoundingClientRect.height="+bcr.height+"\n"+
          "getBoundingClientRect.bottom="+bcr.bottom+"\n"+
          "getBoundingClientRect.right="+bcr.right+"\n"+
          "e.pageX="+e.pageX+"\n"+
          "e.pageY="+e.pageY+"\n"+
          "this.offsetLeft="+this.offsetLeft+"\n"+
          "this.offsetTop="+this.offsetTop+"\n"+
          "relatX="+(e.pageX-this.offsetLeft)+"\n"+
          "relatY="+(e.pageY-this.offsetTop);

        }
       };


      //When we release the mouse button,
      //we must finish the dragging process:
      ///
       document.getElementById("span0000").onmouseup = function(e)
       {
        if(e.button==0)
         this.myDragFlag=false;
       };


       document.getElementById("span0000").onmouseout = function(e)
       {
        if(this.myDragFlag==true)
        {
         //In this code, we basically check that
         //when the mouse slips out from the object
         //area while we are still dragging, we will
         //force moving the object back under the mouse
         //pointer. Here we will check from a logical
         //edge of 48 pixels, and we will move the object
         //back to 90% within those pixels, vertically and/or
         //horizontally. It makes look the object shaky
         //but at least it is minimally functional:
         ///
          var minEdge=48;
          var edgeCorrect=0.90;
          var minEdgeCorrect=(minEdge*edgeCorrect)|0;
          var bcr=this.getBoundingClientRect();
          var bcrw=bcr.width;
          var bcrh=bcr.height;
          if(this.startX<minEdge)
          {
           this.style.left = (e.pageX-minEdgeCorrect)+"px";
          }
          else if(this.startX>bcrw-minEdge)
          {
           this.style.left = (e.pageX-this.startX+minEdgeCorrect)+"px";
          }

          if(this.startY<minEdge)
          {
           this.style.top = (e.pageY-minEdgeCorrect)+"px";
          }
          else if(this.startY>bcrh-minEdge)
          {
           this.style.top = (e.pageY-this.startY+minEdgeCorrect)+"px";
          }
        }
       };

     </script>
     </body>
    </html>

1 个答案:

答案 0 :(得分:3)

onmousemove的事件监听器放在可拖动的div上。因此,如果鼠标离开它,事件将停止发射。它在拖动时会消失,因为它会以一定间隔而不是每个像素触发鼠标移动事件。

要修复它,请将mousemove侦听器放在容器上。

document.body.onmousemove

你可能需要改变你获得坐标的方式。

我想象还有其他方法。但这是最简单的。

修改

当我试图摆弄这个但最终让它起作用时,开始怀疑自己: http://jsfiddle.net/tg33u8mv/3/

document.body.onmousemove = function (e) {
    if (myDragFlag) {
        var draggable = document.getElementById("span0000");
        var bcr = draggable.getBoundingClientRect();
        draggable.style.left = (e.pageX - draggable.startX) + "px";
        draggable.style.top = (e.pageY - draggable.startY) + "px";
    }
};

我将myDragFlag更改为范围变量,而不是this.myDragFlag

<强>加成

在这个版本中,我在拖动时添加一个类。 http://jsfiddle.net/tg33u8mv/4/

此类的CSS目前禁用突出显示,从而显着改善外观。您还可以使其更改颜色或添加阴影以获得良好的效果。