前端teamWeb前端之路让前端飞

原生js实现拖拽功能

2017-04-21  本文已影响753人  小兴nice
在前端技术日新月异,飞速发展的当下,涌现出了很多优秀的开源框架以及优秀的开源组件,这些都是优秀的前端开发者的技术成果。当然,虽然有这么多现成的开源技术成果供我们再开发中使用,但我们不能仅抱着拿来主义的态度,只顾拿来用就行,更多的是要以学习的心态来对待开源技术,对待前端世界,要多汲取他(她)人的经验,且又不忘根本(基础知识),站在巨人的肩膀上继续前行!

js拖拽功能

拖拽功能是前端很多业务场景都能使用到的一种普遍的技术,比如弹窗视口的拖拽等,前端世界的很多优秀框架组件都拥有封装完美的拖拽功能,别人封装的优秀源码,健壮,稳定,同时又优雅美观,自然是值得我们去学习的。这篇文章主要讲解下如何用原生js实现一个简单的拖拽功能。

拖拽原理

对于PC端来说,拖拽功能无非就是鼠标点击,鼠标开始移动,鼠标松开三个步骤,当然这三个步骤里面有拆分了很多的细节,越是健壮,稳定的代码,对细节的处理就越严谨(我们主要讲实现一个简单的拖拽功能,可能有些细节处理得不妥当,待以后再次进行封装)。

接口参数暴露

完美的封装往往都是需要搭配强大的配置参数来维护它的健壮,稳定的。

对于拖拽功能,需要配置的参数通常需要有以下内容:

配置上这些参数,一个简单的拖拽功能就可以使用了。

拖拽示例核心代码

调用方式

new DragView({
    "dragWrap": document.getElementById("drag_wrap"),    //容器,必选
    "dragableArea": document.getElementById("drag_area"),  //可拖拽区域,可选
    "isDrag": true,  //是否可拖拽,可选
    "isDummyWrap": true, //是否需要虚拟拖拽框,可选
    "dummyWrapClass": "dragview_dummy_wrap2" //控制虚拟拖拽框的样式,可选
})

封装的部分代码

DragView.prototype = {
        "constructor": DragView,
        "init": function(){
            var that = this;
            var dragMove = document.createElement("div");
            dragMove.setAttribute("class","dragview_move");
            document.body.appendChild(dragMove);
            that.options.isDrag && (that.options.dragableArea.style.cursor = "move");
            that.options.dragableArea.onmousedown = function(e){
                if(!that.options.dragStatus){
                    that.throttle(function(){
                        that.options.isDrag && that.mouseDown(e);
                    },null,0);
                }
            }.bind(that);
        },
        "getEvent": function(e){
            return e ? e : window.event;
        },
        "extend": function(setting,option){
          for(var attr in setting){
              if(typeof option[attr] != "undefined"){
                  setting[attr] = option[attr];
              }
          }
          return setting;
        },
        "throttle": function(fn,context,delay){
            clearTimeout(fn.timeoutId);
            fn.timeoutId = setTimeout(function(){
                fn.call(context);
            },delay);
        },
        "mouseDown": function(e){
            var that = this;
            var dragMoveArea = "";
            var dragWrap = that.options.dragWrap;
            var events = that.getEvent(e);
            var disX = events.clientX - dragWrap.offsetLeft;
            var disY = events.clientY - dragWrap.offsetTop;
            document.getElementsByClassName("dragview_move")[0].style.display = "block";
            dragWrap.style.position = "absolute";
            dragWrap.style.zIndex = "99999";
            that.options.tempDragWrap = that.options.dragWrap;
            if(that.options.isDummyWrap){
                dragMoveArea = document.createElement("div");
                dragMoveArea.setAttribute("class",that.options.dummyWrapClass);
                dragMoveArea.style.width = dragWrap.clientWidth + "px";
                dragMoveArea.style.height = dragWrap.clientHeight + "px";
                dragMoveArea.style.position = "absolute";
                dragMoveArea.style.zIndex = "99999";
                dragMoveArea.style.top = dragWrap.style.top;
                dragMoveArea.style.left = dragWrap.style.left;
                document.body.appendChild(dragMoveArea);
                that.options.tempDragWrap = dragMoveArea;
            }               
            that.options.dragStatus = true;
            document.onmousemove = function(e){
                that.throttle(function(){
                    var _events = that.getEvent(e);
                    that.mouseMove(_events,disX,disY,dragMoveArea);
                },null,0);
            }
            document.onmouseup = function(){
                that.options.dragStatus && that.mouseUp(dragMoveArea);
            }
        },
        "mouseMove": function(_events,disX,disY,dragMoveArea){
            if(this.options.dragStatus){
                var _x = _events.clientX - disX;
                var _y = _events.clientY - disY;
                var _winW = document.documentElement.clientWidth || document.body.clientWidth;
                var _winH=document.documentElement.clientHeight || document.body.clientHeight;
                var option = {
                    "x": _x,
                    "y": _y,
                    "winX": _winW,
                    "winY": _winH,
                    "dragW": this.options.tempDragWrap.offsetWidth,
                    "dragH": this.options.tempDragWrap.offsetHeight
                };
                this.limiteRange(option);
            }
        },
        "mouseUp": function(dragMoveArea){
            this.options.dragWrap.style.left = this.options.tempDragWrap.style.left;
            this.options.dragWrap.style.top = this.options.tempDragWrap.style.top;
            this.options.dragStatus = false;
            dragMoveArea!="" && document.body.removeChild(dragMoveArea);
            document.getElementsByClassName("dragview_move")[0].style.display = "none";
        },
        "limiteRange": function(option){
            if(option.x <= 0 || option.dragW >= option.winX){
                this.options.tempDragWrap.style.left = "0px";
            }else if((option.x + option.dragW) >= option.winX){
                this.options.tempDragWrap.style.left = (option.winX - option.dragW) + "px";
            }else{
                this.options.tempDragWrap.style.left = option.x + "px";
            }

            if(option.y <= 0 || option.dragH >= option.winY){
                this.options.tempDragWrap.style.top = "0px";
            }
            else if((option.y + option.dragH) >= option.winY){
                this.options.tempDragWrap.style.top = (option.winY - option.dragH) + "px";
            }
            else{
                this.options.tempDragWrap.style.top = option.y + "px";
            }
        }
};

显示效果如下链接:https://webproblem.github.io/hello-world/drag-View/drag.html
具体示例及源码见我的 github , ** 如果喜欢,请记得Star哈!**

原创文章,站在前辈们的经验上的总结,文中如有不正之处,还望指正!

上一篇 下一篇

猜你喜欢

热点阅读