更新于

JS 登录框拖拽

发布于 / 分类: JavaScript / 暂无评论 / 阅读量: 57

登陆框拖拽是比较常用的功能,拖拽的时候要考虑到不能超出可视区域,并且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;
    }

以上完成。

暂无评论

设置
配色方案

布局