正在加载中

最后更新于 2018年11月21日

登陆框拖拽是比较常用的功能,拖拽的时候要考虑到不能超出可视区域,并且ie在html的overflow:hidden;的情况下还是会产生滚动条,废话不多说,我们先看下效果图:

首先做出拖拽功能:

var login = document.getElementById('login');
login.onmousedown = function() {
    this.onmousemove = function(event) {
        var e = event || window.event;
        login.style.top = e.clientY + 'px';
        login.style.left = e.clientX + 'px';
    }
    this.onmouseup = function() {
        this.onmousemove = null;
        this.onmouseup = null;
    }
}

当login被鼠标点击不放并且移动的时候触发事件,login的top和left等于当前鼠标的坐标,当鼠标移出login上方时,删除掉onmousedown 和onmousemove 事件。

这样写后我们会发现虽然login能够有一些拖拽的效果,但是只能往右边和下面移动,因为onmousemove获取鼠标坐标只能在login上方才可以,但实际上我们要在整个可视区域移动,所以onmousemove要改为document.onmousemove才行。

于是改为:

    var login = document.getElementById('login');
    login.onmousedown = function() {
        document.onmousemove = function(event) {
            var e = event || window.event;
            login.style.top = e.clientY + 'px';
            login.style.left = e.clientX + 'px';
        }
        document.onmouseup = function() {
            this.onmousemove = null;
            this.onmouseup = null;
        }
    }

效果图:

这样可视窗口都可以拖拽了,但是每次鼠标左键按住并移动的时候,窗口的左上角总是会自动移动到鼠标下方,这样并不友好,我们应该让窗口自然的移动,所以这里我们要计算出login正确的top和left。

首先我们只能即时获取鼠标的坐标,鼠标在login上点击时,鼠标的xy轴坐标和login的xy轴坐标存在着不固定的距离,如果我们将这个不固定的距离计算出来,然后让鼠标的xy轴减去这个距离,不就可以得到即时的login元素xy轴坐标了。

如图所示,我们只需要将红色的差距算出来,就可以即时获取到login的xy轴坐标了。

var login = document.getElementById('login');
login.onmousedown = function(event) {
    var e = event || window.event;
    var ctop = e.clientY - this.offsetTop;
    var cleft = e.clientX - this.offsetLeft;
    document.onmousemove = function(event) {
        var e = event || window.event;
        login.style.top = e.clientY - ctop + 'px';
        login.style.left = e.clientX - cleft + 'px';
    }
    document.onmouseup = function() {
        this.onmousemove = null;
        this.onmouseup = null;
    }
}

效果图:

即时拖拽效果完成,但是登录框拖拽会超出可视区域,并且ie浏览器在html的overflow:hidden的情况下还可以可以产生滚动条,下面我们要一一修复。

修复超出可视区域:

var login = document.getElementById('login');
login.onmousedown = function(event) {
    var e = event || window.event;
    var ctop = e.clientY - this.offsetTop;
    var cleft = e.clientX - this.offsetLeft;
    document.onmousemove = function(event) {
        var e = event || window.event;
        var logintop = e.clientY - ctop;
        var loginleft = e.clientX - cleft;
        if (logintop < 0) {
            logintop = 0;
        } else if (logintop > getInner().height - login.offsetHeight) {
            logintop = getInner().height - login.offsetHeight;
        }
        if (loginleft < 0) {
            loginleft = 0;
        } else if (loginleft > getInner().width - login.offsetWidth) {
            loginleft = getInner().width - login.offsetWidth;
        }
        login.style.top = logintop + 'px';
        login.style.left = loginleft + 'px';
    }
    document.onmouseup = function() {
        this.onmousemove = null;
        this.onmouseup = null;
    }
}

if判断,如果login的top和left的值大于最大可显示位置(可视宽高减去login自身宽高得到的值),如果大于,就让他的值等于最大可显示位置值,如果小于0说明已经超出了左边和上边,直接就他的值等于0即可,这样就不会超出可视范围。

getInner()是上一篇写的,跨浏览器获取可视宽高的函数。

修复ie产生的滚动条:

在onmousedown事件下使用this.setCapture();

在onmouseup事件下使用this.releaseCapture();

于是:

var login = document.getElementById('login');
login.onmousedown = function(event) {
    var e = event || window.event;
    var ctop = e.clientY - this.offsetTop;
    var cleft = e.clientX - this.offsetLeft;
    if (typeof this.setCapture != 'undefined') {
        this.setCapture();
    }
    document.onmousemove = function(event) {
        var e = event || window.event;
        var logintop = e.clientY - ctop;
        var loginleft = e.clientX - cleft;
        if (logintop < 0) {
            logintop = 0;
        } else if (logintop > getInner().height - login.offsetHeight) {
            logintop = getInner().height - login.offsetHeight;
        }
        if (loginleft < 0) {
            loginleft = 0;
        } else if (loginleft > getInner().width - login.offsetWidth) {
            loginleft = getInner().width - login.offsetWidth;
        }
        login.style.top = logintop + 'px';
        login.style.left = loginleft + 'px';
    }
    document.onmouseup = function() {
        this.onmousemove = null;
        this.onmouseup = null;
        if (typeof this.releaseCapture != 'undefined') {
            this.releaseCapture();
        }
    }
}

这样基本就完成了,开始封装到Base中去。

封装至Base:

Base.prototype.drag = function() {
        for (var i = 0; i < this.arr.length; i++) {
            this.arr[i].onmousedown = function(event) {
                var e = getEvent(event);
                var _this = this;
                var ctop = e.clientY - _this.offsetTop;
                var cleft = e.clientX - _this.offsetLeft;
                if (typeof _this.setCapture != 'undefined') {
                    _this.setCapture();
                }
                document.onmousemove = function(event) {
                    var e = getEvent(event);
                    var logintop = e.clientY - ctop;
                    var loginleft = e.clientX - cleft;
                    if (logintop < 0) {
                        logintop = 0;
                    } else if (logintop > getInner().height - login.offsetHeight) {
                        logintop = getInner().height - login.offsetHeight;
                    }
                    if (loginleft < 0) {
                        loginleft = 0;
                    } else if (loginleft > getInner().width - login.offsetWidth) {
                        loginleft = getInner().width - login.offsetWidth;
                    }
                    login.style.top = logintop + 'px';
                    login.style.left = loginleft + 'px';
                }
                document.onmouseup = function() {
                    this.onmousemove = null;
                    this.onmouseup = null;
                    if (typeof this.releaseCapture != 'undefined') {
                        _this.releaseCapture();
                    }
                }

            }
            return this;
        }


        //跨浏览返回event

        function getEvent(e) {
            return e || window.event;
        }

调用代码:

$().getId('login').drag();

修复两个bug:

  1. 当login里面没有内容是,拖拽时错位!
  2. 当浏览器窗口发生改变时,login会自动居中

当login里面没有内容是,拖拽时错位!

在旧版火狐上会有这个问题,处理方法就是将onmousedown 的默认行为阻止即可。

Base.prototype.drag = function() {
        for (var i = 0; i < this.arr.length; i++) {
            this.arr[i].onmousedown = function(event) {
                preDef(event);
                var e = getEvent(event);
                var _this = this;
                var ctop = e.clientY - _this.offsetTop;
                var cleft = e.clientX - _this.offsetLeft;
                if (typeof _this.setCapture != 'undefined') {
                    _this.setCapture();
                }
                document.onmousemove = function(event) {
                    var e = getEvent(event);
                    var logintop = e.clientY - ctop;
                    var loginleft = e.clientX - cleft;
                    if (logintop < 0) {
                        logintop = 0;
                    } else if (logintop > getInner().height - login.offsetHeight) {
                        logintop = getInner().height - login.offsetHeight;
                    }
                    if (loginleft < 0) {
                        loginleft = 0;
                    } else if (loginleft > getInner().width - login.offsetWidth) {
                        loginleft = getInner().width - login.offsetWidth;
                    }
                    login.style.top = logintop + 'px';
                    login.style.left = loginleft + 'px';
                }
                document.onmouseup = function() {
                    this.onmousemove = null;
                    this.onmouseup = null;
                    if (typeof this.releaseCapture != 'undefined') {
                        _this.releaseCapture();
                    }
                }

            }
            return this;
        }


        //跨浏览返回event

        function getEvent(e) {
            return e || window.event;
        }
//跨浏览器阻止默认行为
function preDef(event) {
    var e = event || window.event;
    if (typeof e.preventDefault != 'undefined') {
        e.preventDefault();
    } else {
        e.returnValue = false;
    }
}

当浏览器窗口发生改变时,login会自动居中

由于在弹出登录框时我们使用了resize()函数,当浏览器窗口发生变化是,自动居住,但是我们加了拖拽功能后就不需要自动居中了,我们只需要当login超出可视区域是自动移动到能见区域;于是:

Base.prototype.resize = function(fn) {
    for (var i = 0; i < this.arr.length; i++) {
        var element = this.arr[i];
        window.onresize = function() {
            fn();
            if (element.offsetLeft > getInner().width - element.offsetWidth) {
                element.style.left = getInner().width - element.offsetWidth + 'px';
            }
            if (element.offsetTop > getInner().height - element.offsetHeight) {
                element.style.top = getInner().height - element.offsetHeight + 'px';
            }
        }
    }
    return this;
}

在窗口发生变化时,判断login的xy轴坐标是否大于最大可见xy轴坐标,如果大于,说明login看不到了,于是让他的xy轴坐标等于最大可见xy轴坐标即可。

resize()函数调用的function中也不需要再对login加.center()居中函数了。

$().getId('login').css('clip', 'auto').css('opacity', '1').center().Masked().resize(function() {
    if ($().getId('login').css('opacity') == '1') {
        $().getId('login').Masked();
    };
});

css部分,我们只需要为login顶部加一个十字光标,表示可以移动,由于我的上部分只用了class为title的h2标题,所以只要加上cursor: move;即可。

    #login>.login_title {
        font-weight: normal;
        font-size: 16px;
        line-height: 30px;
        letter-spacing: 1px;
        background-color: #eee;
        cursor: move;
    }

以上完成。

  • weixiao kaixin tushetou jingkong deyi fanu liezui liuhan daku ganga bishi nanguo lihai qian yiwen numu tu yi haixiu se fadai minyan hehe henkaixin huaji biyiyan kuanghan maimeng shui xiaku penqi zhangzui pen aini ye niu laji ok chigua renshi kongbu shuai xiaoxiese touxiao huaixiao jingnu chihuai kaisang xiaoku koubi zhuangbi lianhong kanbujian shafa zhijing xiangjiao dabian yaowan redjing lazhu rizhi duocang chixigua hejiu xixi xiaopen goukun xiaobuchu shenme wusuowei guancha lajing chouyan xiaochi bie zhadanzui zhadanxiao