JS案列-JS特效第四天

1. client

clientTop、clientLeft:

clientTop:盒子的上boder

clientLeft:盒子的左border

clientWidth与clientHeight

1、在有DTD情况下:

document.body.clientWidth、document.body.clientHeight:显示的是body的宽和高,document.documentElement.clientWidth、document.documentElement.clientHeight:显示的是body可视范围的宽和高,

2、在无DTD情况下:

document.body.clientWidth、document.body.clientHeight显示的是body可视范围的宽和高;

document.documentElement.clientWidth、document.documentElement.clientHeight显示的是body的高和body可视范围的宽(IE中显示的都是body可视范围的宽和高)

3、不管有没有DTD:

window.innerWidth、window.innerHeight:显示的都是浏览器可视范围的宽和高,包括浏览器的头部和滚动条部分(IE678无法识别window.innerWidth)

调用者的区别:

1、clientTop、clientLeft、clientWidth、clientHeight调用者是元素

2、clientX、clientY调用者是event对象

client、scroll、offset区别:

clientWidth = width + padding

clientHeight = height + padding

offsetWidth = width + padding + border

offsetHeight = height + padding + border

scrollWidth = 内容宽度(不包含border)

scrollHeight = 内容高度(不包含border)

注意事项:IE67,scrollHeight即使不超出盒子,它的值也是内容的高度

兼容写法:

<script>
    document.title = client().width + "    " + client().height;
    //新事件:浏览器大小变化事件(浏览器哪怕大小变化1px也会触动这个事件)
    window.onresize = function () {
        document.title = client().width + "    " + client().height;
    }

    //获取屏幕可视区域的宽高
    function client() {
        if (window.innerHeight !== undefined) {
            return {
                "width": window.innerWidth,
                "height": window.innerHeight
            }
        } else if (document.compatMode === "CSS1Compat") {
            return {
                "width": document.documentElement.clientWidth,
                "height": document.documentElement.clientHeight
            }
        } else {
            return {
                "width": document.body.clientWidth,
                "height": document.body.clientHeight
            }
        }
    }
</script>

注意事项:window.innerWidth、window.innerHeight:显示的都是浏览器可视范围的宽和高,包括浏览器的头部和滚动条部分

2. Window 尺寸

有三种方法能够确定浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)。

对于I E、Chrome、Firefox、Opera 以及 Safari:

window.innerHeight - 浏览器窗口的内部高度
window.innerWidth - 浏览器窗口的内部宽度

对于 Internet Explorer 8、7、6、5:
document.documentElement.clientHeight
document.documentElement.clientWidth

或者
document.body.clientHeight
document.body.clientWidth
实用的 JavaScript 方案(涵盖所有浏览器):

兼容写法
var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;

var h=window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

新事件 浏览器大小变化事件(浏览器哪怕大小变化1px也会触动这个事件)
window.onresize = function () {
document.title = client().width + " "+ client().height;
}

<script>

    //新事件:浏览器大小变化事件(浏览器哪怕大小变化1px也会触动这个事件)
    window.onresize = function () {
        document.title = client().width + "    "+ client().height;
    }

    //获取屏幕可视区域的宽高
    function client(){
        if(window.innerHeight !== undefined){
            return {
                "width": window.innerWidth,
                "height": window.innerHeight
            }
        }else if(document.compatMode === "CSS1Compat"){
            return {
                "width": document.documentElement.clientWidth,
                "height": document.documentElement.clientHeight
            }
        }else{
            return {
                "width": document.body.clientWidth,
                "height": document.body.clientHeight
            }
        }
    }
</script>

3. 判断浏览器大小决定显示方式

秀一下:

源码:

   <script>
        //需求:浏览器每次更改大小,判断是否符合某一标准然后给背景上色。
        //  // >960红色,大于640小于960蓝色,小于640绿色。
        //步骤:
        //1.老三步
        //2.判断。
        //3.上色

        //1.老三步
        window.onresize = fn;
        //页面加载的时候直接执行一次函数,确定浏览器可视区域的宽,给背景上色
        fn();

        //封装成函数,然后指定的时候去调用和绑定函数名
        function fn() {
            //2.判断。
            //3.上色
            if(client().width>960){
                document.body.style.backgroundColor = "red";
            }else if(client().width>640){
                document.body.style.backgroundColor = "blue";
            }else{
                document.body.style.backgroundColor = "green";
            }
        }

//获取屏幕可视区域的宽高
function client(){
    if(window.innerHeight !== undefined){
        return {
            "width": window.innerWidth,
            "height": window.innerHeight
        }
    }else if(document.compatMode === "CSS1Compat"){
        return {
            "width": document.documentElement.clientWidth,
            "height": document.documentElement.clientHeight
        }
    }else{
        return {
            "width": document.body.clientWidth,
            "height": document.body.clientHeight
        }
    }
}
    </script>

4.判断屏幕大小

    document.title = window.screen.width + "    "+ window.screen.height;

5. 冒泡初体验

首先我们要先知道什么是冒泡。
假设有两个盒子box1和box2,box1包含box2。它们两同时都有一个相同的事件就是onclick,当我们点击box2时,它的onclick事件会执行,但随后它的父元素box1的onclick也会被执行,这就是冒泡。
捕获正好和冒泡相反。


看图

下面代码里面的false是允许冒泡,true是允许捕获。如果不写默认是false;

   box1.addEventListener("click", function () {
       alert("我是box1");
   },false);

   box2.addEventListener("click", function () {
       alert("我是box2");
   },false);

事件被激发的时候,会有三个传播阶段。
三个阶段是:捕获、冒泡和目标阶段
事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。
事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。

知识点:

  • 冒泡顺序
    IE 6.0:
    div -> body -> html -> document
    其他浏览器:
    div -> body -> html -> document -> window
    不是所有的事件都能冒泡。以下事件不冒泡:blur、focus、load、unload、onmouseenter
    onmouseleave

阻止冒泡的方法
假如想在box2上面阻止冒泡。
w3c的方法是:(火狐、谷歌、IE11)
event.stopPropagation()
IE10以下则是使用:event.cancelBubble = true//现在已废弃
兼容代码如下:
var event = event || window.event;
if(event && event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}

6. 模态框取消

点击模态框外,让整个模态框消失。
效果展示:


点击背景也能让其消失

源码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        body,html {
            height: 100%;
            padding: 0;
            margin: 0;
        }
        .mask {
            width: 100%;
            height: 100%;
            position: fixed;
            top: 0;
            left: 0;
            display: none;
            background: rgba(0, 0, 0, 0.6);
        }
        .login {
            width: 400px;
            height: 300px;
            cursor: pointer;
            background-color: #fff;
            margin: 200px auto;
        }
    </style>
</head>
<body>
    <div class="mask">
        <div class="login" id="login"></div>
    </div>
    <a href="#">注册</a>
    <a href="#">登陆</a>
    <script src="jquery1.0.0.1.js"></script>
    <script>
        //需求:点击登录按钮,显示模态框。点击出去login以外的所有盒子隐藏模态框。
        //步骤:
        //1.给登录绑定事件
        //2.给document绑定事件,因为可以冒泡,只要判断,点击的不是login,那么隐藏模态框


        //1.给登录绑定事件
        var mask = document.getElementsByClassName("mask")[0];
        var a = document.getElementsByTagName("a")[1];

        a.onclick = function (event) {
            //显示模态框
            show(mask);

            //阻止冒泡
            event = event || window.event;
            if(event && event.stopPropagation){
                event.stopPropagation();
            }else{
                event.cancelBubble = true;
            }

        }

        //2.给document绑定事件,因为可以冒泡,只要判断,点击的不是login,那么隐藏模态框
        document.onclick = function (event) {
            //获取点击按钮后传递过来的值。
            event = event || window.event;

            //兼容获取事件触动时,被传递过来的对象
//            var aaa = event.target || event.srcElement;
            var aaa = event.target?event.target:event.srcElement;

            console.log(event.target);

            //判断目标值的ID是否等于login,如果等于不隐藏盒子,否则隐藏盒子。
            if(aaa.id !== "login"){
                mask.style.display = "none";
            } 

            // 也可以这样写
            // if(event.target.id !== "login"){
            //     mask.style.display = "none";
            // }
        }
    </script>

</body>
</html>

隐藏模态框小结
判断当前对象
IE678 event.srcElement(事件源)
火狐/谷歌等 event.target(事件源)
兼容写法获取元素ID:
var event = event || window.event;
var targetId = event.target ? event.target.id : event.srcElement.id;

7. 事件委托

普通的事件绑定,没有办法为JS新创建的元素绑定事件。所以我们要使用冒泡的特性,事件委托!

源代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        li {
            height: 30px;
            line-height: 30px;
            margin: 3px 0;
            background-color: red;
            cursor: pointer;
        }
    </style>
</head>
<body>
<button>创建4个移民li</button>
<ul>
    <li>我是土著li</li>
    <a href="#">我是土著li</a>
    <li>我是土著li</li>
    <li>我是土著li</li>
    <a href="#">我是土著li</a>
    <li>我是土著li</li>
</ul>
<script>

    var liArr = document.getElementsByTagName("li");
    var ul = document.getElementsByTagName("ul")[0];
    var btn = document.getElementsByTagName("button")[0];

//    for(var i=0;i<liArr.length;i++){
//        liArr[i].onclick = function () {
//            alert("我是土著li");
//        }
//    }

    btn.onclick = function () {
        for(var i=1;i<=4;i++){
            var newLi = document.createElement("li");
            var newA = document.createElement("a");
            newLi.innerHTML = "我是移民li";
            newA.innerHTML = "我是移民a";
            newA.href = "#";
            ul.appendChild(newLi);
            ul.appendChild(newA);
        }
    }
    //普通的事件绑定,没有办法为新创建的元素绑定事件。所以我们要使用冒泡的特性,事件委托!
    //事件委托
    ul.onclick = function (event) {
        //获取事件触动的时候传递过来的值
        event = event || window.event;
        var aaa = event.target?event.target:event.srcElement;
        //判断标签名,如果是li标签弹窗
        if(aaa.tagName === "LI"){//必须是大写,因为tagName的返回值是大写
            alert("我是li");
        }
    }
</script>
</body>
</html>

事件委托小结
(先绑定,后创建的元素没有事件)
阻止冒泡,阻止自己像父系盒子冒泡。
所有的泡泡冒泡到阻止位置停止向上冒泡
event.target是在事件被触动的时候把事件源绑定到event的target属性中。而之前的target是我们自定义的一个变量触动

8.缓动动画的完善(加强)

之前封装的动画缺点:

  • 1.只能放入一个属性。(一个方法只能操作一个属性)
  • 2.只能获取行内式,不能获取内嵌和外链样式。导致我们获取left值的时候,用offsetLeft模拟。
  • 3.一次性放入多个属性值。
  • 先看一下获取元素属性值和赋值方法
    给属性赋值:(既能获取又能赋值)
    div.style.width 单个赋值
    div.style[“width”] 变量赋值
    获取属性值:(只能获取)
    window.getComputedStyle(div,null).width;单个获取
    window.getComputedStyle(div,null)[“width”];变量获取
    div.currentStyle.width; IE678
    div.currentStyle[“width”]; IE678

1.只能放入一个属性。(方法只能操作一种属性)的解决办法。
源码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        div {
            position: absolute; width: 100px; height: 100px;background-color: pink;
        }
    </style>
</head>
<body>
    <button>运动到400</button>
    <button>宽度变为400</button>
    <div></div>
    <script>
        var btnArr = document.getElementsByTagName("button");
        var div = document.getElementsByTagName("div")[0];
        btnArr[0].onclick = function () {
            animate(div,"left",400);
        }
        btnArr[1].onclick = function () {
            animate(div,"width",400);
        }
        //参数变为3个
        function animate(ele,attr,target){
            //先清定时器
            clearInterval(ele.timer);
            ele.timer = setInterval(function () {
                console.log(ele.timer)
                //四部
                var leader = parseInt(getStyle(ele,attr)) || 0;
                //1.获取步长
                var step = (target - leader)/10;
                //2.二次加工步长
                step = step>0?Math.ceil(step):Math.floor(step);
                leader = leader + step;
                //3.赋值
                ele.style[attr] = leader + "px";
                 //4.清除定时器
                if(Math.abs(target-leader)<=Math.abs(step)){
                    ele.style[attr] = target + "px";
                    clearInterval(ele.timer);
                }
            },25);
        }
        //兼容方法获取元素样式
        function getStyle(ele,attr){
            if(window.getComputedStyle){
                return window.getComputedStyle(ele,null)[attr];
            }
            return ele.currentStyle[attr];
        }
    </script>
</body>
</html>

2.让多个属性同时使用+开闭原则清除定时器+回调函数
源码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        div {
            position: absolute;
            top: 40px;
            left: 10px;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <button>运动到400然后回来</button>
    <div></div>
    <script>
        var btnArr = document.getElementsByTagName("button");
        var div = document.getElementsByTagName("div")[0];
        btnArr[0].onclick = function () {
            var json1 = {"left":300,"top":200,"width":300,"height":200};
            var json2 = {"left":10,"top":30,"width":100,"height":100};
            animate(div,json1,function () {animate(div,json2);});
        }
        //参数变为3个
        function animate(ele,json,fn){
            //先清定时器
            clearInterval(ele.timer);
            ele.timer = setInterval(function () {
                //开闭原则
                var bool = true;


                //遍历属性和值,分别单独处理json
                //attr == k(键)    target == json[k](值)
                for(var k in json){
                    //四部
                    var leader = parseInt(getStyle(ele,k)) || 0;
                    //1.获取步长
                    var step = (json[k] - leader)/10;
                    //2.二次加工步长
                    step = step>0?Math.ceil(step):Math.floor(step);
                    leader = leader + step;
                    //3.赋值
                    ele.style[k] = leader + "px";
                    //4.清除定时器
                    //判断: 目标值和当前值的差大于步长,就不能跳出循环
                    //不考虑小数的情况:目标位置和当前位置不相等,就不能清除清除定时器。
                    if(json[k] !== leader){
                        bool = false;
                    }
                }

                console.log(1);
                //只有所有的属性都到了指定位置,bool值才不会变成false;
                if(bool){
                    clearInterval(ele.timer);
                    //所有程序执行完毕了,现在可以执行回调函数了
                    //只有传递了回调函数,才能执行
                    if(fn){
                        fn();
                    }
                }
            },25);
        }
        //兼容方法获取元素样式
        function getStyle(ele,attr){
            if(window.getComputedStyle){
                return window.getComputedStyle(ele,null)[attr];
            }
            return ele.currentStyle[attr];
        }
    </script>
</body>
</html>

9.手风琴案例

效果是这样的:


手风琴.gif

图片width:800,高度随意。
源码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        ul{list-style: none}
        *{margin:0; padding:0;}
        div{
            width: 1200px;
            height: 400px;
            margin:50px auto;
            border:1px solid red;
            overflow: hidden;

        }
        div li {
            width: 20%;
            height: 400px;
            float: left;
        }
        div ul {
            width: 1300px;
        }
    </style>
    <script src="../jquery1.0.0.1.js"></script>
    <script>
        window.onload = function () {
            //需求:鼠标放入到li中该盒子变宽,其他的盒子变窄。移开大盒子,回复原样。
            //步骤:
            //1.给li添加背景
            //2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
            //3.移开大盒子,回复原样


            var div = document.getElementsByTagName("div")[0];
            var liArr = div.getElementsByTagName("li");
            //1.给li添加背景
            for(var i=0;i<liArr.length;i++){
                liArr[i].style.background = "url(images/"+(i+1)+".jpg) no-repeat";

                //2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
                liArr[i].onmouseover = function () {
                    //排他思想
                    for(var j=0;j<liArr.length;j++){
                        //引用框架实现宽度变窄
                        animate(liArr[j],{"width":100});
                    }
                    //剩下他自己
                    animate(this,{"width":800})
                }
            }

            //3.移开大盒子,回复原样
            div.onmouseout = function () {
                for(var j=0;j<liArr.length;j++){
                    //引用框架实现宽度变窄
                    animate(liArr[j],{"width":240});
                }
            }
        }
    </script>
</head>
<body>
<div>
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>
</body>
</html>

9.模拟360开机弹窗关闭

效果是这样的:

模拟360开机弹窗

图片找个类似的就行,切成上下两部分。
源码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        .box{
            width: 322px;
            position: fixed;
            bottom:0;
            right:0;
        }
        span{
            position: absolute;
            top:0;
            right:0;
            width:30px;
            height: 20px;
            cursor: pointer;
        }
    </style>
    <script src="../jquery1.0.0.1.js"></script>
    <script>
        window.onload = function () {
            //需求:下面的盒子高度变为0,然后大盒子的宽在变为0.
            var guanbi = document.getElementById("guanbi");
            var box = guanbi.parentNode;
            var b = document.getElementById("b");

            guanbi.onclick = function () {
                //下面的盒子高度变为0,然后大盒子的宽在变为0.
                animate(b,{"height":0}, function () {
                    animate(box,{"width":0});
                });
            }
        }
    </script>
</head>
<body>
    <div class="box">
        <span id="guanbi"></span>
        <div class="hd" id="t">
            <img src="images/t.jpg" alt=""/>
        </div>
        <div class="bd" id="b">
            <img src="images/b.jpg" alt=""/>
        </div>
    </div>
</body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342