首页 » JavaScript » JS 登录弹窗

最后更新于 2018年11月16日

我们需要做一个当用户点击登录按钮时,在页面中央弹出一个登录窗口,然后点击窗口的关闭按钮可以关闭,并且在登录窗口期间会有遮罩层防止用户点击到其他元素,而且此时浏览器是无法滚轮滑动的。

先看下效果图:


请输入图片描述

html代码:

<header id="header">
    <div class="center">
        <img src="https://www.mulingyuer.com/usr/themes/Yodu/images/logo.png" alt="" class="logo" />
        <ul class="nav">
            <li class="nav-li nav-login">登录</li>
            <li class="nav-li nav-confin">
                个人设置
                <ul class="nav-menu">
                    <li class="menu-li">设置</li>
                    <li class="menu-li">换肤</li>
                    <li class="menu-li">帮助</li>
                    <li class="menu-li">退出</li>
                </ul>
            </li>
        </ul>
    </div>
</header>
<div id="login">
    <i class="login_off">X</i>
    <h2 class="login_title">网站登录</h2>
    <form action="" id="login_form">
        <div class="user">账 号:<input type="text" name="user" class="text" /></div>
        <div class="pass">密 码:<input type="password" name="pass" class="text" /></div>
        <div class="buttom"><input type="button" name="submit" value="登录" class="submit" /></div>
        <div class="other">注册新用户 | 忘记密码?</div>
    </form>
</div>

css代码:

#login {
        position: fixed;
        color: #666;
        width: 350px;
        font-size: 14px;
        border: 1px solid orange;
        text-align: center;
        background-color: #fff;
        clip: rect(0 0 0 0);
        opacity: 0;
        transition: all .5s;
    }
    #login_form {
        line-height: 0;
        background-color: #fff;
    }
    #login > .login_off {
        position: absolute;
        top: 0;right: 0;
        margin-top: 8px;
        margin-right: 8px;
        color: #fff;
        font-style: normal;
        width: 14px;
        line-height: 14px;
        background-color: orange;
        cursor: pointer;
    }
    #login > .login_title {
        font-weight: normal;
        font-size: 16px;
        line-height: 30px;
        letter-spacing: 1px;
        background-color:  #eee;
    }
    .user,.pass,.buttom {
        line-height: 40px;
    }
    .user,.buttom,.other {
        padding: 10px 0;
    }
    #login input.text {
        background-color: #fff;
        border: 1px solid #eee;
        height: 25px;
        width: 200px;
    }
    .buttom > input.submit {
        padding: 5px 14px 5px 22px;
        color: #fff;
        letter-spacing: 8px;
        font-weight: bold;
        border: 1px solid green;    
        background-color: #00d82e;
        background-image: linear-gradient(rgba(255,255,255,.3) 30%,rgba(0,0,0,.2));
        border-radius: 2px;
        cursor: pointer;
    }
    .other {
        text-align: right;
        padding-right: 8px;
        font-size: 12px;
    }

JS代码:

接着上一章的代码,我们要做一个修改,首先就是我们之前只有一个选项:个人设置 所以class用的是通用的nav-li,然后js部分也是通过这个class去获取这个对象,但是现在我们有多个了,如果还是用之前的方法,就会导致获取的对象是所有的li元素,然后在class的if判断时候也会出错,因为我们之前用的是:this.arr[i].className == className;而我们现在是给li加上了多个class,为此要先改动一下.class()方法。

Base.prototype.getclass = function(className, idName) {
    var node = null;
    if (arguments.length == 2) {
        node = document.getElementById(idName);
    } else {
        node = document;
    }
    var elements = node.getElementsByTagName('*');
    for (var i = 0; i < elements.length; i++) {
        if (elements[i].className.match(className)) {
            this.arr.push(elements[i]);
        }
    }
    return this;
}

我们通过match的方法去判断,如果搜到了就传入arr中。

css部分我们已经做好了,我们现在只需要为 登录 选项添加click事件,然后弹出ID为login的div元素。

ligin元素我们使用了clip: rect(0 0 0 0);opacity: 0;做隐藏,所以,显示的时候做对应修改就可以了。

首先我们先获取到对应的元素并添加cilck事件:

$().getclass('nav-login','header').click(function(){});

然后在事件函数里面获取到login元素,然后将它的css改为clip: auto;opacity: 1;

$().getclass('nav-login', 'header').click(function() {
    $().getId('login').css('clip','auto').css('opacity','1');
});

点击是可以显示了,但是我们还要点击login里的关闭,将窗口隐藏,那也很简单,一样获取关闭按钮的元素对象,然后添加click事件,然后再css改回去。

$().getclass('login_off','login').click(function(){
    $().getId('login').css('clip','').css('opacity','');
});

将css的值传入为空的字符,这样行内css就被自动删除了。

现在显示和隐藏都可以了,我们还要将login设置为居中,那么我们要用到获取可视宽度/高度和获取元素宽度/高度的js。

获取可视宽度:document.documentElement.clientWidth;
获取可视高度:document.documentElement.clientHeight;

这里火狐最新版63他的高度会有问题,他获取的是body元素的高度,所以火狐只能使用w3c提供的innerHeight来获取,这个innerHeight新版的浏览器都已经支持,但是旧版ie不支持,所以还要做个判断。

typeof innerHeight == 'undefined' ? document.documentElement.clientHeight : innerHeight;

获取元素宽度:offsetWidth;
获取元素高度:offsetHeight;

这里获取的是border+padding+content三个盒模型的值。

于是添加一个center()自动居中的公用方法:

Base.prototype.center = function(){
    var left = document.documentElement.clientWidth;
    var top = typeof innerHeight == 'undefined' ? document.documentElement.clientHeight : innerHeight;
    for(var i = 0;i<this.arr.length;i++)  {
        this.arr[i].style.top = (top - this.arr[i].offsetHeight)/2 + 'px';
        this.arr[i].style.left = (left - this.arr[i].offsetWidth)/2 + 'px';
    }
    return this;
}

调用:

$().getclass('nav-login','header').click(function(){
        $().getId('login').css('clip','auto').css('opacity','1').center();
    });
    $().getclass('login_off','login').click(function(){
        $().getId('login').css('clip','').css('opacity','');
    });

自动居中后,我们发现,这个居中只有在每次刷新后才会居中,如果用户没有刷新,只是改变了浏览器窗口的大小,这时候login还是显示在第一次出现的位置,所以我们还要做个resize事件,让浏览器窗口发生变化时重新调整位置。

Base.prototype.resize = function(fn){
    window.onresize = fn;
    return this;
}

自动居中没必要再写一遍获取这个对象啊,直接传入一个函数,在函数里面重新运行一遍居中就可以了。

$().getclass('nav-login','header').click(function(){
        $().getId('login').css('clip','auto').css('opacity','1').center().resize(function(){
    $().getId('login').center()
});
    });
    $().getclass('login_off','login').click(function(){
        $().getId('login').css('clip','').css('opacity','');
    });

这样我们基本就做好了,细节还要做一下,有以下几个地方:

  • 选项点击 登录 改变背景色增加交互体验
  • 添加遮罩层,防止用户误触
  • 有遮罩层时页面不能滚动,无遮罩层可以滚动

选项点击 登录 改变背景色增加交互体验

    $().getclass('nav-login', 'header').hover(function() {
        $(this).css('background-color', 'rgba(0,0,0,.3)');
    }, function() {
        $(this).css('background-color', 'rgba(0,0,0,0)');
    });

添加遮罩层,防止用户误触

#login {
    position: fixed;
    color: #666;
    width: 350px;
    font-size: 14px;
    border: 1px solid orange;
    text-align: center;
    background-color: #fff;
    clip: rect(0 0 0 0);
    opacity: 0;
    z-index: 1;
    transition: all .5s;
}

#login::before {
    content: "";
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: rgba(0, 0, 0, .3);
    z-index: -1;
}

通过伪元素扩大形成遮罩层,这是伪元素在其他元素之上,用户点击遮罩层无法点击到下面的元素,由于是伪元素,所以省了显示和隐藏的js步骤,直接和login是同步的,但是也有一个缺点:有时候我们会添加点击遮罩层可以关闭login和遮罩层的交互效果,但是因为伪元素无法添加事件的,所以有利也有弊吧!

有遮罩层时页面不能滚动,无遮罩层可以滚动

这里我们只要在用户点击login后将html元素overflow:hidden;即可,用户关闭login再还原css,于是:

$().getclass('nav-login','header').click(function(){
        $().getId('login').css('clip','auto').css('opacity','1').center().resize(function(){$().getId('login').center()});
        $().getTagName('html').css('overflow','hidden');
    });
    $().getclass('login_off','login').click(function(){
        $().getId('login').css('clip','').css('opacity','');
        $().getTagName('html').css('overflow','');
    });

当html的滚动条隐藏后,整个页面会自动的往右偏移,体验非常不好,为此我们利用一个小小的hack的方法,直接为布局的元素自动模拟出一条滚动条的宽度占用着,这样不管页面滚动条有还是没有,位置都是固定的了。

.center {
    max-width: 500px;
    margin: 0 auto;
    padding-left: calc(100vw - 100%);  /*模拟滚动条宽度*/
}

然后将js调用代码集中一下如下:

$().getclass('nav-login', 'header').hover(function() {
    $(this).css('background-color', 'rgba(0,0,0,.3)');
}, function() {
    $(this).css('background-color', 'rgba(0,0,0,0)');
});
$().getclass('nav-login', 'header').click(function() {
    $().getId('login').css('clip', 'auto').css('opacity', '1').center().resize(function() {
        $().getId('login').center()
    });
    $().getTagName('html').css('overflow', 'hidden');
});
$().getclass('login_off', 'login').click(function() {
    $().getId('login').css('clip', '').css('opacity', '');
    $().getTagName('html').css('overflow', '');
});
  • 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