UI组件之浮出层的拖拽

Posted 完毕先生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UI组件之浮出层的拖拽相关的知识,希望对你有一定的参考价值。

上次总结了一下简单的浮出层的设计,不了解的可以猛戳下面这条链接:

UI组件之浮出层

这次的这篇总结主要是参考的这篇文章:js拖拽事件实例,不过自己多做了一点分析

这次来总结一下浮出层的拖拽,期间遇到了一些小问题,不过最后也解决了,这里也总结一下。

首先,我们要实现的效果是浮出层在鼠标点击之后随着鼠标移动,松开之后停止移动,并且边框不得超出边界。

网上很多教程已经说得很清楚了,这里就再啰嗦两句,这个过程总共分为三步:

  1. 鼠标点下之时用onmousedown事件记录鼠标点下时与浮出层的相对位置
  2. 用onmousemove事件让浮出层跟随鼠标移动,每当用户将鼠标移动一个像素,就会发生一个 mousemove 事件,我们在这个事件中改变浮出层的位置即可
  3. 用onmouseup事件在鼠标松开时清除onmousemove中的事件

还需要一些额外的知识,是关于offsetWidth,offsetLeft等等,在网上找到一篇文章不错(图画的比较清楚),链接如下:

关于offsetWidth、offsetLeft等概念的理解

接下来是代码实现:

1、计算鼠标与浮出层的相对位置

 horizen.onmousedown=function(ev) //鼠标按下浮出层
  {
    var oEvent=ev||event;//这里是为了浏览器兼容,大家可以上网去查一下
disX=oEvent.clientX-horizen.offsetLeft; /*鼠标的X坐标减去浮出层的左边距就等于disX, 这个disX是用于确定鼠标移动浮出层时鼠标点和浮出层之间的左面距离,
这个距离是不会变的,通过这个新鼠标的X坐标减去disX就是浮出层的Left
*/ disY=oEvent.clientY-horizen.offsetTop;
   ……
……
}
  • 其中的clientX是鼠标相对于整个屏幕在X轴上的位置,clientY是鼠标相对于整个屏幕在Y轴上的位置

2、根据鼠标的移动计算出浮出层的offsetLeft应有的距离,从而改变浮出层的位置,并根据此距离判断浮出层是否超出边界

 horizen.onmousedown=function(ev) 
  {
    var oEvent=ev||event; 
    disX=oEvent.clientX-horizen.offsetLeft; 
    disY=oEvent.clientY-horizen.offsetTop; 
    document.onmousemove=function(ev) 
    {
      var oEvent=ev||event;  //此处是为了浏览器兼容,大家可以上网去查一下
      var oLeft=oEvent.clientX-disX; //新鼠标X坐标减去disX,也就是鼠标移动浮出层后的Left
      var oTop=oEvent.clientY-disY; 
      if(oLeft<0) //浮出层的Left小于0,也就是移出了左边
      {
        oLeft=0; //就把浮出层的Left设置为0,就不能移出左边
      }
      else if(oLeft>document.documentElement.clientWidth-horizen.offsetWidth) //屏幕宽度减去浮出层的宽度就得出了浮出层到达最右边的宽度
      {
        oLeft=document.documentElement.clientWidth-horizen.offsetWidth; //如果Left大于这个像素,就把Left设置为这个像素
      }
      if(oTop<0) 
      {
        oTop=0; 
      }
      else if(oTop>document.documentElement.clientHeight-horizen.offsetHeight)
      {
        oTop=document.documentElement.clientHeight-horizen.offsetHeight; 
      }
      console.log(oLeft);
      horizen.style.left=oLeft+\'px\'; //浮出层的Left设置为新鼠标X坐标减去disX的值
      horizen.style.top=oTop+\'px\'; 
    };
    return false; //阻止FireFox的默认事件 bug,(额……不太理解,有大神知道希望赐教)
  }
  • 以上注释只写了左右的,上下的是一样的

3.鼠标松开时清除onmousemove中的事件

document.onmouseup=function() //鼠标松开时
{
     document.onmousemove=null; //把鼠标移动清除
};

这样我们的浮出层的拖拽就做好了……

一切看似如此完美,可是当我打开浏览器调试的时候却发现,浮出层左边拖拽时会超出边界,右边会到达不了边界,上下也是这样

浏览器也并没有报错,检查了代码也没有错误,最后打了个断点调试了一下,发现在计算鼠标相对位置时,disX(只讨论x轴上的的值比较小,究其原因是因为offsetLeft过大,上网查了一下以后发现,原来是translate的原因,元素利用translate移动后不会影响offsetLeft的值,意思就是它是按我向左移动前的那个浮出层计算offsetLeft的,那么offset的值自然就会变大了,并且其变大的值就是我向左移动的值(浮出层的width是400px;我想左移动了自身的50%也就是200px),所以我们需要对判定的条件进行一些修改:

 if(oLeft<200) //移动前浮出层的Left小于200,也就是移出左边
      {
        oLeft=0; //就把浮出层的Left设置为200,就不能移出左边
      }
 else if(oLeft>document.documentElement.clientWidth-horizen.offsetWidth+200) //屏幕宽度减去DIV的宽度就得出了浮出层到达最右边的宽度,
      {
        oLeft=document.documentElement.clientWidth-horizen.offsetWidth+200; //如果Left大于这个值就把Left设置为这个值
      }

上下也根据浮出层的高度改一下就可以了

这样我们的浮出层拖拽的效果就真的做好了~

 

 

 

以上是关于UI组件之浮出层的拖拽的主要内容,如果未能解决你的问题,请参考以下文章

关于弹出层的拖拽,封装

jquery-ui sortable 使用实例

js实现拖拽效果

Vue:制作一个通用的拖拽组件

Vue:制作一个通用的拖拽组件

基于jquery UI的拖拽摇摆效果插件