zoukankan      html  css  js  c++  java
  • javascript的拖放(第2部分)

    实现手柄拖动的功能,就是把mousedown的事件侦听器放到handle中。由于我们原先程序的骨架搭建得比较好,添加新功能非常容易。
    #
      (handle || el).onmousedown = dragstart;
    

    但这不够人性化,最好是我们输入一个类名作为handle的参数,拖动类会自动根据此类名在其子孙元素寻找此元素。

        if(handle){
          var cls = new RegExp("(^|\\s)" + handle + "(\\s|$)");
          for(var i=0,l=el.childNodes.length;i <l;i++){
            var child = el.childNodes[i];
            if(child.nodeType == 1 && cls.test(child.className)){
              _handle = child;
              break;
            }
          }
        }
    

    相应地方修改为:

    #
      (_handle || el).onmousedown = dragstart;
    

    有时如果拖动元素是个非常复杂,包含相当多东西,这样拖起来很吃内存,这时是不是拖动一个空元素是不是好一些呢?我们可以克隆原来的拖动元素,并把它加入原来元素的后面(相同z-Index,后面的会放到前面的前面)。如果要求是用手柄拖动,我们把原来的手柄也克隆过来就是。

          if(ghosting){ // ghosting为可选参数,表示使用克隆体拖动
            _ghost = el.cloneNode(false);
            el.parentNode.insertBefore(_ghost,el.nextSibling);
            if(_handle){
              _handle = _handle.cloneNode(false);
              _ghost.appendChild(_handle);
            }
              !+"\v1"? _ghost.style.filter = "alpha(opacity=50)" : _ghost.style.opacity = 0.5;
          }
    

    我们还可以增添一些回调函数(onStart,onDrag,onEnd),如果用户没有实现回调函数,我们给个空函数(function(){})它就好了。

    像拖动时显示元素的坐标,我们也可以做成可选参数coords。默认为true,并在手柄上显示,但这样会覆盖住原来的一些东西,我们在拖动前把它保存到一个变量中,拖动后再还原。

    另,如果是一个范围中拖动,如一个指定的容器或浏览器的可视区,当拖动元素存在margin时,其右边与下边可能会超出容器。因此我们必须取出其相应的margin,当右边与下边的坐标大于容器右边或下边的坐标时,强逼元素往左边与上边移动相应的值,那个值不用说就是margin值。我们用一个简单的getStyle()函数来取margin值,因此设置元素的margin时请以px为单位,否则在IE中会计算错误。

      var getStyle = function(el, style){
        if(!+"\v1"){
          style = style.replace(/\-(\w)/g, function(all, letter){
            return letter.toUpperCase();
          });
          var value = el.currentStyle[style];
          (value == "auto")&&(value = "0px" );
          return value;
        }else{
          return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
        }
      }
    

    最后一个较为重要的功能,当元素往右边或下边移动,让元素永远留在可视区。这怎样做到呢?我们计算元素右下角的坐标(right与bottom),然后再计算出浏览器可视区的宽与高,当right大于宽时,就让它们的差值作为浏览器的scrollLeft,bottom的情形相仿。

          if(scroll){ //表示让滚动条与元素一起移动
            var doc = isQuirk ? document.body : document.documentElement;
            doc = options.container || doc;
            var a = getCoords(el).left + el.offsetWidth;
            var b = doc.clientWidth;
            if (a > b){
              doc.scrollLeft += a - b;
            }
            var c = getCoords(el).top + el.offsetHeight;
            var d = doc.clientHeight;
            if (c > d){
              doc.scrollTop += c - d;
            }
          }
    

    最后函数扩展成以下样子,功能比较多,下附文档说明:

      //辅助函数1
      var getCoords = function(el){
        var box = el.getBoundingClientRect(),
        doc = el.ownerDocument,
        body = doc.body,
        html = doc.documentElement,
        clientTop = html.clientTop || body.clientTop || 0,
        clientLeft = html.clientLeft || body.clientLeft || 0,
        top  = box.top  + (self.pageYOffset || html.scrollTop  ||  body.scrollTop ) - clientTop,
        left = box.left + (self.pageXOffset || html.scrollLeft ||  body.scrollLeft) - clientLeft
        return { 'top': top, 'left': left };
      };
      //辅助函数2
      var getStyle = function(el, style){
        if(!+"\v1"){
          style = style.replace(/\-(\w)/g, function(all, letter){
            return letter.toUpperCase();
          });
          var value = el.currentStyle[style];
          (value == "auto")&&(value = "0px" );
          return value;
        }else{
          return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
        }
      }
      //============================
            var Drag = function(id){
            var el = document.getElementById(id),
            isQuirk = document.documentMode ? document.documentMode == 5 : document.compatMode && document.compatMode != "CSS1Compat",
            options  = arguments[1] || {},
            container = options.container || document.documentElement,
            limit = options.limit,
            lockX = options.lockX,
            lockY = options.lockY,
            ghosting = options.ghosting,
            handle = options.handle,
            revert = options.revert,
            scroll = options.scroll,
            coords =  options.coords,
            onStart =  options.onStart || function(){},
            onDrag =  options.onDrag || function(){},
            onEnd =  options.onEnd || function(){} ,
            marginLeft = parseFloat(getStyle(el,"margin-left")),
            marginRight = parseFloat(getStyle(el,"margin-right")),
            marginTop =  parseFloat(getStyle(el,"margin-top")),
            marginBottom = parseFloat(getStyle(el,"margin-bottom")),
            cls,
            _handle,
            _ghost,
            _top,
            _left,
            _html;
            el.lockX = getCoords(el).left;
            el.lockY = getCoords(el).top;
            el.style.position = "absolute";
            if(handle){
              cls = new RegExp("(^|\\s)" + handle + "(\\s|$)");
              for(var i=0,l=el.childNodes.length;i<l;i++){
                var child = el.childNodes[i];
                if(child.nodeType == 1 && cls.test(child.className)){
                  _handle = child;
                  break;
                }
              }
            }
            _html = (_handle || el).innerHTML;
            var dragstart = function(e){
              e = e || window.event;
              el.offset_x = e.clientX - el.offsetLeft;
              el.offset_y = e.clientY - el.offsetTop;
              document.onmouseup = dragend;
              document.onmousemove = drag;
              if(ghosting){
                _ghost = el.cloneNode(false);
                el.parentNode.insertBefore(_ghost,el.nextSibling);
                if(_handle){
                  _handle = _handle.cloneNode(false);
                  _ghost.appendChild(_handle);
                }
                  !+"\v1"? _ghost.style.filter = "alpha(opacity=50)" : _ghost.style.opacity = 0.5;
              }
              (_ghost || el).style.zIndex = ++Drag.z;
              onStart();
              return false;
            }
            var drag = function(e) {
              e = e || window.event;
              el.style.cursor = "pointer";
                !+"\v1"? document.selection.empty() : window.getSelection().removeAllRanges();
              _left = e.clientX - el.offset_x ;
              _top = e.clientY - el.offset_y;
              if(scroll){
                var doc = isQuirk ? document.body : document.documentElement;
                doc = options.container || doc;
                options.container && (options.container.style.overflow = "auto");
                var a = getCoords(el).left + el.offsetWidth;
                var b = doc.clientWidth;
                if (a > b){
                  doc.scrollLeft = a - b;
                }
                var c = getCoords(el).top + el.offsetHeight;
                var d = doc.clientHeight;
                if (c > d){
                  doc.scrollTop = c - d;
                }
              }
              if(limit){
                var _right = _left + el.offsetWidth ,
                _bottom = _top + el.offsetHeight,
                _cCoords = getCoords(container),
                _cLeft = _cCoords.left,
                _cTop = _cCoords.top,
                _cRight = _cLeft + container.clientWidth,
                _cBottom = _cTop + container.clientHeight;
                _left = Math.max(_left, _cLeft);
                _top = Math.max(_top, _cTop);
                if(_right > _cRight){
                  _left = _cRight - el.offsetWidth - marginLeft - marginRight;
                }
                if(_bottom > _cBottom){
                  _top = _cBottom - el.offsetHeight  - marginTop - marginBottom;
                }
              }
              lockX && ( _left = el.lockX);
              lockY && ( _top = el.lockY);
              (_ghost || el).style.left = _left + "px";
              (_ghost || el).style.top = _top  + "px";
              coords && ((_handle || _ghost || el).innerHTML = _left + " x " + _top);
              onDrag();
            }
    
            var dragend = function(){
              document.onmouseup = null;
              document.onmousemove = null;
              _ghost && el.parentNode.removeChild(_ghost);
              el.style.left = _left + "px";
              el.style.top = _top +"px";
              (_handle || el).innerHTML = _html;
              if(revert){
                el.style.left = el.lockX   + "px";
                el.style.top = el.lockY  + "px";
              }
              onEnd();
            }
            Drag.z = 999;
            (_handle || el).onmousedown = dragstart;
          }
    
    参数 类型 说明
    id string 必选,拖动元素的ID
    container object 可拖的范围,必须为拖动元素的父级元素,是否为定位元素无所谓。
    limit boolean 默认false,与container配合使用。当值为true时,它会以container或浏览器的可视区作拖动范围。
    lockX boolean 默认false。当值为true时,锁定X轴,只允许上下移动。
    lockY boolean 默认false。当值为true时,锁定Y轴,只允许左右移动。
    handle string 手柄的类名,当设置了此参数后,只允许用手柄拖动元素。
    ghosting boolean 默认false。当值为true时,会生成一个与拖动元素相仿的影子元素,拖动时只拖动影子元素,以减轻内存消耗。
    revert boolean 默认false。当值为true时,让拖动元素在拖动后回到原来的位置。
    coords boolean 默认false。拖动时在手柄或影子元素上显示元素的坐标。
    scroll boolean 默认false。当值为true时,允许滚动条随拖动元素移动。
    onStart function 在拖动前鼠标按下的那一瞬执行。
    onDrag function 在拖动时执行。
    onEnd function 在拖动后鼠标弹起的那一瞬执行。

  • 相关阅读:
    docker in docker
    docker社区的geodata/gdal镜像dockerfile分析
    howto:在构建基于debian的docker基础镜像时,更换国内包源
    使用Visual Studio 2017构建.Net Core的Docker镜像
    步骤:asp.net core中使用identifyserver4颁发令牌
    部署:阿里云ECS部署Docker CE
    问题:调用 ASP.Net Core WebAPI的HTTP POST方法时,从 [FromBody] 中读取的 MongoDB GeoJsonObjectModel成员总是null
    《.NET 微服务:适用于容器化 .NET 应用的体系结构》关键结论
    SQL数据库注入防范 ASP.NET Globle警告
    数据库中的恶意字符批处理
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1563955.html
Copyright © 2011-2022 走看看