zoukankan      html  css  js  c++  java
  • JS实现元素拖动

    实现1

    参考文献:http://www.cnblogs.com/cloudgamer/archive/2008/11/17/Drag.html

    1.1 拖放效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <!-- saved from url=(0037)http://sandbox.runjs.cn/show/hbhrnv2g -->
    <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            
            <title>
                拖放效果
            </title>
        </head>
        
        <body>
            
            <div id="idContainer" style="position: relative;">
                <div id="idDrag" style="position: absolute;">
                    <div id="idHandle">
                    </div>
                </div>
            </div>
            
            <input id="idReset" type="button" value="复位">
            <input id="idLock" type="button" value="锁定">
            <input id="idLockX" type="button" value="锁定水平">
            <input id="idLockY" type="button" value="锁定垂直">
            <input id="idLimit" type="button" value="范围锁定">
            <input id="idLimitOff" type="button" value="取消范围锁定">
            <br>
            拖放状态:
            <span id="idShow">
                未开始
            </span>
        
    
    
            <style>#idContainer{
        border:10px solid #990000;
        width:600px;
        height:300px;
    }
    #idDrag{
        border:5px solid #C4E3FD;
        background:#C4E3FD;
        width:50px;
        height:50px;
        top:50px;
        left:50px;
    }
    #idHandle{
        cursor:move;
        height:25px;
        background:#0000FF;
        overflow:hidden;
    }</style>
                    <script>//以下是实现的插件
    var isIE = (document.all) ? true: false;
    
    var $ = function(id) {
        return "string" == typeof id ? document.getElementById(id) : id;
    };
    
    var Class = {
        create: function() {
            return function() {
                this.initialize.apply(this, arguments);
            }
        }
    }
    
    var Extend = function(destination, source) {
        for (var property in source) {
            destination[property] = source[property];
        }
    }
    
    var Bind = function(object, fun) {
        return function() {
            return fun.apply(object, arguments);
        }
    }
    
    var BindAsEventListener = function(object, fun) {
        return function(event) {
            return fun.call(object, (event || window.event));
        }
    }
    
    var CurrentStyle = function(element) {
        return element.currentStyle || document.defaultView.getComputedStyle(element, null);
    }
    
    function addEventHandler(oTarget, sEventType, fnHandler) {
        if (oTarget.addEventListener) {
            oTarget.addEventListener(sEventType, fnHandler, false);
        } else if (oTarget.attachEvent) {
            oTarget.attachEvent("on" + sEventType, fnHandler);
        } else {
            oTarget["on" + sEventType] = fnHandler;
        }
    };
    
    function removeEventHandler(oTarget, sEventType, fnHandler) {
        if (oTarget.removeEventListener) {
            oTarget.removeEventListener(sEventType, fnHandler, false);
        } else if (oTarget.detachEvent) {
            oTarget.detachEvent("on" + sEventType, fnHandler);
        } else {
            oTarget["on" + sEventType] = null;
        }
    };
    
    //拖放程序
    var Drag = Class.create();
    Drag.prototype = {
        //拖放对象
        initialize: function(drag, options) {
            this.Drag = $(drag); //拖放对象
            this._x = this._y = 0; //记录鼠标相对拖放对象的位置
            this._marginLeft = this._marginTop = 0; //记录margin
            //事件对象(用于绑定移除事件)
            this._fM = BindAsEventListener(this, this.Move);
            this._fS = Bind(this, this.Stop);
    
            this.SetOptions(options);
    
            this.Limit = !!this.options.Limit;
            this.mxLeft = parseInt(this.options.mxLeft);
            this.mxRight = parseInt(this.options.mxRight);
            this.mxTop = parseInt(this.options.mxTop);
            this.mxBottom = parseInt(this.options.mxBottom);
    
            this.LockX = !!this.options.LockX;
            this.LockY = !!this.options.LockY;
            this.Lock = !!this.options.Lock;
    
            this.onStart = this.options.onStart;
            this.onMove = this.options.onMove;
            this.onStop = this.options.onStop;
    
            this._Handle = $(this.options.Handle) || this.Drag;
            this._mxContainer = $(this.options.mxContainer) || null;
    
            this.Drag.style.position = "absolute";
            //透明
            if (isIE && !!this.options.Transparent) {
                //填充拖放对象
                with(this._Handle.appendChild(document.createElement("div")).style) {
                    width = height = "100%";
                    backgroundColor = "#fff";
                    filter = "alpha(opacity:0)";
                    fontSize = 0;
                }
            }
            //修正范围
            this.Repair();
            addEventHandler(this._Handle, "mousedown", BindAsEventListener(this, this.Start));
        },
        //设置默认属性
        SetOptions: function(options) {
            this.options = { //默认值
                Handle: "",
                //设置触发对象(不设置则使用拖放对象)
                Limit: false,
                //是否设置范围限制(为true时下面参数有用,可以是负数)
                mxLeft: 0,
                //左边限制
                mxRight: 9999,
                //右边限制
                mxTop: 0,
                //上边限制
                mxBottom: 9999,
                //下边限制
                mxContainer: "",
                //指定限制在容器内
                LockX: false,
                //是否锁定水平方向拖放
                LockY: false,
                //是否锁定垂直方向拖放
                Lock: false,
                //是否锁定
                Transparent: false,
                //是否透明
                onStart: function() {},
                //开始移动时执行
                onMove: function() {},
                //移动时执行
                onStop: function() {} //结束移动时执行
            };
            Extend(this.options, options || {});
        },
        //准备拖动
        Start: function(oEvent) {
            if (this.Lock) {
                return;
            }
            this.Repair();
            //记录鼠标相对拖放对象的位置
            this._x = oEvent.clientX - this.Drag.offsetLeft;
            this._y = oEvent.clientY - this.Drag.offsetTop;
            //记录margin
            this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
            this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;
            //mousemove时移动 mouseup时停止
            addEventHandler(document, "mousemove", this._fM);
            addEventHandler(document, "mouseup", this._fS);
            if (isIE) {
                //焦点丢失
                addEventHandler(this._Handle, "losecapture", this._fS);
                //设置鼠标捕获
                this._Handle.setCapture();
            } else {
                //焦点丢失
                addEventHandler(window, "blur", this._fS);
                //阻止默认动作
                oEvent.preventDefault();
            };
            //附加程序
            this.onStart();
        },
        //修正范围
        Repair: function() {
            if (this.Limit) {
                //修正错误范围参数
                this.mxRight = Math.max(this.mxRight, this.mxLeft + this.Drag.offsetWidth);
                this.mxBottom = Math.max(this.mxBottom, this.mxTop + this.Drag.offsetHeight);
                //如果有容器必须设置position为relative或absolute来相对或绝对定位,并在获取offset之前设置
                ! this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || CurrentStyle(this._mxContainer).position == "absolute" || (this._mxContainer.style.position = "relative");
            }
        },
        //拖动
        Move: function(oEvent) {
            //判断是否锁定
            if (this.Lock) {
                this.Stop();
                return;
            };
            //清除选择
            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
            //设置移动参数
            var iLeft = oEvent.clientX - this._x,
            iTop = oEvent.clientY - this._y;
            //设置范围限制
            if (this.Limit) {
                //设置范围参数
                var mxLeft = this.mxLeft,
                mxRight = this.mxRight,
                mxTop = this.mxTop,
                mxBottom = this.mxBottom;
                //如果设置了容器,再修正范围参数
                if ( !! this._mxContainer) {
                    mxLeft = Math.max(mxLeft, 0);
                    mxTop = Math.max(mxTop, 0);
                    mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
                    mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
                };
                //修正移动参数
                iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag.offsetWidth), mxLeft);
                iTop = Math.max(Math.min(iTop, mxBottom - this.Drag.offsetHeight), mxTop);
            }
            //设置位置,并修正margin
            if (!this.LockX) {
                this.Drag.style.left = iLeft - this._marginLeft + "px";
            }
            if (!this.LockY) {
                this.Drag.style.top = iTop - this._marginTop + "px";
            }
            //附加程序
            this.onMove();
        },
        //停止拖动
        Stop: function() {
            //移除事件
            removeEventHandler(document, "mousemove", this._fM);
            removeEventHandler(document, "mouseup", this._fS);
            if (isIE) {
                removeEventHandler(this._Handle, "losecapture", this._fS);
                this._Handle.releaseCapture();
            } else {
                removeEventHandler(window, "blur", this._fS);
            };
            //附加程序
            this.onStop();
        }
    };
    
    //以下是调用以上插件实现拖动
    var drag = new Drag("idDrag", {
        mxContainer: "idContainer",
        Handle: "idHandle",
        Limit: true,
        onStart: function() {
            $("idShow").innerHTML = "开始拖放";
        },
        onMove: function() {
            $("idShow").innerHTML = "left:" + this.Drag.offsetLeft + ";top:" + this.Drag.offsetTop;
        },
        onStop: function() {
            $("idShow").innerHTML = "结束拖放";
        }
    });
    
    $("idReset").onclick = function() {
        drag.Limit = true;
        drag.mxLeft = drag.mxTop = 0;
        drag.mxRight = drag.mxBottom = 9999;
        drag.LockX = drag.LockY = drag.Lock = false;
    }
    
    $("idLock").onclick = function() {
        drag.Lock = true;
    }
    $("idLockX").onclick = function() {
        drag.LockX = true;
    }
    $("idLockY").onclick = function() {
        drag.LockY = true;
    }
    $("idLimit").onclick = function() {
        drag.mxRight = drag.mxBottom = 200;
        drag.Limit = true;
    }
    $("idLimitOff").onclick = function() {
        drag.Limit = false;
    }</script>
        
    <!-- Generated by RunJS (Sun Mar 13 10:40:31 CST 2016) 0ms --></body></html>
    View Code

    效果:http://sandbox.runjs.cn/show/hbhrnv2g

    1.2 简易拖放效果

    <!DOCTYPE html>
    <!-- saved from url=(0037)http://sandbox.runjs.cn/show/xq0yj0sd -->
    <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            
            <title>简易拖放效果</title>
        </head>
        <body>
            <div id="central" style="position: absolute;">
                此拖动效果要将被拖动元素布局设为absolute
            </div>
        
    
            <style>#central
    {
        background-color:pink;
        width:300px;
        height:200px;
    }</style>
                    <script>var isIE = (document.all) ? true: false;
    
    var $ = function(id) {
        return "string" == typeof id ? document.getElementById(id) : id;
    };
    
    var Class = {
        create: function() {
            return function() {
                this.initialize.apply(this, arguments);
            }
        }
    }
    
    var Extend = function(destination, source) {
        for (var property in source) {
            destination[property] = source[property];
        }
    }
    
    var Bind = function(object, fun) {
        return function() {
            return fun.apply(object, arguments);
        }
    }
    
    var BindAsEventListener = function(object, fun) {
        return function(event) {
            return fun.call(object, (event || window.event));
        }
    }
    
    function addEventHandler(oTarget, sEventType, fnHandler) {
        if (oTarget.addEventListener) {
            oTarget.addEventListener(sEventType, fnHandler, false);
        } else if (oTarget.attachEvent) {
            oTarget.attachEvent("on" + sEventType, fnHandler);
        } else {
            oTarget["on" + sEventType] = fnHandler;
        }
    };
    
    function removeEventHandler(oTarget, sEventType, fnHandler) {
        if (oTarget.removeEventListener) {
            oTarget.removeEventListener(sEventType, fnHandler, false);
        } else if (oTarget.detachEvent) {
            oTarget.detachEvent("on" + sEventType, fnHandler);
        } else {
            oTarget["on" + sEventType] = null;
        }
    };
    
    //拖放程序
    var SimpleDrag = Class.create();
    SimpleDrag.prototype = {
        //拖放对象,触发对象
        initialize: function(drag) {
            this.Drag = $(drag);
            this._x = this._y = 0;
            this._fM = BindAsEventListener(this, this.Move);
            this._fS = Bind(this, this.Stop);
            this.Drag.style.position = "absolute";
            addEventHandler(this.Drag, "mousedown", BindAsEventListener(this, this.Start));
        },
        //准备拖动
        Start: function(oEvent) {
            this._x = oEvent.clientX - this.Drag.offsetLeft;
            this._y = oEvent.clientY - this.Drag.offsetTop;
            addEventHandler(document, "mousemove", this._fM);
            addEventHandler(document, "mouseup", this._fS);
        },
        //拖动
        Move: function(oEvent) {
            this.Drag.style.left = oEvent.clientX - this._x + "px";
            this.Drag.style.top = oEvent.clientY - this._y + "px";
        },
        //停止拖动
        Stop: function() {
            removeEventHandler(document, "mousemove", this._fM);
            removeEventHandler(document, "mouseup", this._fS);
        }
    };
    
    new SimpleDrag("central");</script>
        
    <!-- Generated by RunJS (Sun Mar 13 10:41:02 CST 2016) 0ms --></body></html>
    View Code

    效果:http://sandbox.runjs.cn/show/xq0yj0sd

    实现2

    <!DOCTYPE html>
    <!-- saved from url=(0037)http://sandbox.runjs.cn/show/o8sbts8t -->
    <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body><html">
    
    
    <title>
    D类
    </title>
    
    
    
    <div id="block1_outer">
    <div id="block1_inner" onmousedown="var wc = this;D.start(wc, null, function (property) {
    var node = wc.parentNode;
    var a = D.pos(node), b = D.pos(wc);
    node.style.left = property.left - b.x + a.x + &#39;px&#39;;
    
    node.style.top = property.top - b.y + a.y + &#39;px&#39;;
    }, null);"></div>
    </div>
    
    <div id="block2_outer" onmousedown="var wc = this;D.start(wc, null, function (property) {
    wc.style.left = property.left + &#39;px&#39;;
    wc.style.top = property.top + &#39;px&#39;;
    }, null);"></div>
    
    
            <style>html, body {
        margin:0;
    }
    
    
    #block1_outer
    {
        position:relative;
        width:100px;
        height:100px;
        background-color:#000000;
    }
    #block1_inner
    {
        position:absolute;
        width:20px;
        height:20px;
        line-height:20px;
        left:50%;
        top:50%;
        margin:-10px 0 0 -10px;
        
        background-color:#F00;
        text-align:center;
        cursor:move;
    }
    
    #block2_outer
    {
        width:50px;
        height:50px;
        line-height:50px;
        text-align:center;
        background-color:#F00;
        position:absolute;
        
        cursor:move;
    }
    
    #block2_inner
    {
        position:absolute;
        width:20px;
        height:20px;
        line-height:20px;
        left:50%;
        top:50%;
        margin:-10px 0 0 -10px;
        
        background-color:#F00;
        text-align:center;
        cursor:move;
    }</style>
                    <script>//实现拖动的插件
    !! window.__defineGetter__ && !/MSIE/.test(navigator.userAgent) &&
    function() { ! window.opera && window.__defineGetter__('event',
        function() {
            //兼容Event对象
            var o = arguments.callee;
            do {
                if (o.arguments[0] instanceof Event) return o.arguments[0];
            } while ( o = o . caller );
            return null;
        });
    
        window.attachEvent = Document.prototype.attachEvent = Element.prototype.attachEvent = function(type, listener, capture) {
            //兼容attachEvent方法
            return this.addEventListener(new String(type).substr(2), listener, capture || false);
        };
    
        window.detachEvent = Document.prototype.detachEvent = Element.prototype.detachEvent = function(type, listener, capture) {
            //兼容detachEvent方法
            return this.removeEventListener(new String(type).substr(2), listener, capture || false);
        };
    
    } ();
    var D = {
        //拽补助类
        lock: false
    
        ,
        dom: function() {
            //document相关属性
            return {
                left: document.documentElement.scrollLeft,
                top: document.documentElement.scrollTop,
                 document.documentElement.clientWidth,
                height: document.documentElement.clientHeight,
                body: document.documentElement
            };
        }
    
        ,
        mos: function(e) {
            //获取鼠标绝对位置
            var dom = this.dom();
    
            return {
                'x': dom.left + e.clientX,
                'y': dom.top + e.clientY
            }
        }
    
        ,
        pos: function(o) {
            //获取元素绝对位置
            var x = 0,
            y = 0;
            do {
                x += o.offsetLeft, y += o.offsetTop;
            } while ( o = o . offsetParent );
            return {
                'x': x,
                'y': y
            };
        }
    
        ,
        start: function(element, startEventHandler, moveEventHandler, stopEventHandler) {
            //移动开始
            if (this.lock) return;
            else this.lock = true;
            //先上锁安全。。。:D
            var pos = this.pos(element) //元素位置
            ,
            mos = this.mos(window.event) //鼠标位置
            ,
            eventHandlers = {
                MF: null,
                EF: null
            }
            //事件记录
            ,
            property = {
                x: mos.x - pos.x,
                y: mos.y - pos.y,
                left: pos.x,
                top: pos.y
            }
            //属性
            ,
            _MF = this.move(moveEventHandler, property) //移动过程事件闭包
            ,
            _EF = this.stop(element, stopEventHandler, eventHandlers);
            //移动停止事件闭包
            try {
                document.selection && document.selection.empty && (document.selection.empty(), 1) || window.getSelection && window.getSelection().removeAllRanges();
            } catch(exp) {}
    
            document.attachEvent('onmousemove', _MF);
            //鼠标移动
            document.attachEvent('onmouseup', _EF);
            //鼠标释放
            element.setCapture ? (element.setCapture(), element.attachEvent('onlosecapture', _EF)) : window.attachEvent('onblur', _EF);
            //鼠标捕获丢失则释放
            eventHandlers.MF = _MF,
            eventHandlers.EF = _EF;
    
            startEventHandler && startEventHandler(property);
            //直接传过去。。。请误污染- -
        }
    
        ,
        move: function(moveEventHandler, property) {
            //移动中
            var wc = this;
    
            return function(e) {
                var mos = wc.mos(e || window.event),
                dom = wc.dom();
                window.getSelection && window.getSelection().removeAllRanges();
    
                /MSIE/.test(navigator.userAgent) &&
                function() {
                    //IE滚屏
                    if (mos.x > dom.left + dom.width) dom.body.scrollLeft = mos.x - dom.width;
                    else if (mos.x < dom.left) dom.body.scrollLeft = mos.x;
    
                    if (mos.y > dom.top + dom.height) dom.body.scrollTop = mos.y - dom.height;
                    else if (mos.y < dom.top) dom.body.scrollTop = mos.y;
                } ();
    
                property.left = mos.x - property.x,
                property.top = mos.y - property.y;
    
                moveEventHandler && moveEventHandler(property);
                //直接传过去。。。请误污染- -;
            };
        }
    
        ,
        stop: function(element, stopEventHandler, eventHandlers) {
            //移动结束
            var wc = this;
            return function(e) {
                document.detachEvent('onmousemove', eventHandlers.MF);
                document.detachEvent('onmouseup', eventHandlers.EF);
                element.setCapture ? (element.detachEvent('onlosecapture', eventHandlers.EF), element.releaseCapture()) : window.detachEvent('onblur', eventHandlers.EF);
                wc.lock = false;
                //事件都干掉了可以放心解锁了
                stopEventHandler && stopEventHandler();
            };
        }
    
    };</script>
        
    <!-- Generated by RunJS (Sun Mar 13 10:41:11 CST 2016) 1ms --></html"></body></html>
    View Code

     效果:http://sandbox.runjs.cn/show/o8sbts8t

  • 相关阅读:
    判断输入的年份是闰年还是平年!!!
    键盘接收数,接收运算符号进行运算!!
    eclipse项目上如何传到码云上!新手,简单易懂,希望对你有所帮助。
    jquery dialog弹出框简单写法和一些属性的应用,写的不好,大佬勿喷!谢谢!
    新手冒泡排序,随机生成十个数。
    新手java九九乘法表
    Lambda表达式
    如何删除gitee仓库的文件
    Collection方法
    java冒泡排序的几种写法
  • 原文地址:https://www.cnblogs.com/z-sm/p/5271376.html
Copyright © 2011-2022 走看看