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

先看下效果图:


请输入图片描述

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', '');
});
分类: JavaScript 标签: JS 登录弹窗遮罩层防止页面滚动

评论

暂无评论数据

暂无评论数据

目录