Improving JavaScript Dragging Effect

老子叫甜甜 提交于 2019-12-12 03:22:25

问题


I have managed to implement a simple JavaScript dragging effect to create "panel windows" inside a webpage, in which I can drag the object from any corner or position. I have only used the onmousedown (to indicate a possible dragging), onmousemove (to perform dragging) and onmouseup (to stop dragging) events.

It works well except when I drag the object too near an edge and move the mouse even at a normal speed. When I move the mouse towards an area outside the object, the dragging fails until I move again to the object's area, and I have to click the object to stop dragging it.

It's like the mouse is too fast, but obviously it doesn't happen in native application windows because they are better implemented.

What checks could I add to my current code so it doesn't fail as much? It currently seems to support a little bit of this problem by somehow handling the onmouseout event, but when it happens the window shakes to return the mouse pointer to the object area, and it doesn't look so good.

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:


Your event listener for onmousemove is placed on the draggable div. So if the mouse goes off of it, the event stops firing. And it goes off while dragging because it fires mousemove events at intervals instead of every pixel.

To fix it, put the mousemove listener on the container.

document.body.onmousemove

And you will probably need to change how you get the coordinates.

There are other ways too I imagine. But that's the easiest.

Edit

Started to doubt myself when I tried to fiddle this but eventually got it working: 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";
    }
};

And I changed myDragFlag to a scoped variable instead of this.myDragFlag.

Bonus

In this version I add a class when it is dragging. http://jsfiddle.net/tg33u8mv/4/

The CSS for this class currently disables highlighting, significantly improving the look. You could also make it change color or add a shadow for a nice effect.



来源:https://stackoverflow.com/questions/27450376/improving-javascript-dragging-effect

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!