JavaScript学习(二)动画

Offset

offsetWidth和offsetHight

检测盒子自身宽高+padding+border。
这两个属性,他们绑定在了所有的节点元素上。获取之后,只要调用这两个属性,我们就能够获取元素节点的宽和高。
offset宽/高 = 盒子自身的宽/高 + padding +border;
offsetWidth = width+padding+border;
offsetHeight = Height+padding+border;

offsetLeft和offsetTop

检测距离父盒子有定位的左/上面的距离。
返回距离上级盒子(带有定位)左边s的位置,如果父级都没有定位则以body为准,offsetLeft 从父亲的padding 开始算,父亲的border 不算。在父盒子有定位的情况下,offsetLeft == style.left(去掉px)。

offsetParent

检测父系盒子中带有定位的父盒子节点。
1、返回改对象的父级 (带有定位)
如果当前元素的父级元素没有进行CSS定位(position为absolute或 relative,fixed),offsetParent为body。
2、如果当前元素的父级元素中有CSS定位(position为absolute或relative,fixed),offsetParent取最近的那个父级元素。

offsetLeft和style.left区别

一、最大区别在于offsetLeft可以返回没有定位盒子的距离左侧的位置。
而 style.left不可以
二、offsetTop 返回的是数字,而 style.top 返回的是字符串,除了数字外还带有单位:px。
三、offsetTop 只读,而 style.top 可读写。(只读是获取值,可写是赋值)
四、如果没有给 HTML 元素指定过 top 样式,则style.top 返回的是空字符串。

缓动动画

原理

leader=leader+(target-leader)/10;
盒子位置 = 盒子本身位置+(目标位置-盒子本身位置)/ 10;
动画原理 = 盒子位置 + 步长(步长越来越小)。

offsetLeft和style.left的值的获取问题

offsetLeft获取盒子距离左侧具有定位的父盒子的距离(没有的body),四舍五入取整。
Style.left获取的是具体值。

案例

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
            left: 0;
        }
    </style>
</head>
<body>
<button>运动到200</button>
<button>运动到400</button>
<div></div>

<script>

    var btn = document.getElementsByTagName("button");
    var div = document.getElementsByTagName("div")[0];

    //运动到200
    btn[0].onclick = function () {
        animate(div,200);
    }
    //运动到400
    btn[1].onclick = function () {
        animate(div,400);
    }

    //封装缓动动画
    function animate(ele,target) {
        //先清定时器
        clearInterval(ele.timer);
        //定义定时器
        ele.timer = setInterval(function () {
           //获取步长,步长应该是越来越小
            var step = (target - ele.offsetLeft)/10;
            //大于0向上取整,小于0向下取整
            step = step>0 ? Math.ceil(step) : Math.floor(step);
            //动画原理: 目标位置 = 当前位置 + 步长
            ele.style.left = ele.offsetLeft + step + "px";
            //检测缓动动画有没有停止
            if(Math.abs(target - ele.offsetLeft) <= Math.abs(step)){
                //处理小数赋值
                ele.style.left = target + "px";
                clearInterval(ele.timer);
            }
        },30);
    }

</script>

</body>
</html>

Scroll

scrollWidth和scrollHeight

检测盒子的宽高,不包括border。调用者:节点元素、属性。盒子内容的宽高。(如果有内容超出了,显示内容的高度)。
兼容性:IE567可以比盒子小。IE8+火狐谷歌不能比盒子小。

scrollWidth和scrollHeight不包括border和margin
scrollWidth = width + padding;

scrollTop和scrollLeft

网页,被浏览器遮挡的头部和左边部分。
兼容性:
一、未声明 DTD(谷歌只认识他)
document.body.scrollTop
二、已经声明DTD(IE678只认识他)
document.documentElement.scrollTop
三、火狐/谷歌/ie9+以上支持的
window.pageYOffset

只要页面滚动无论向左向右,向上向下,哪怕只有1px,都会触动onscroll事件。

   window.onscroll = function () {
        //兼容写法
        document.title = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0;
   }

获取title、body、head、html标签

document.title — 文档标题;
document.head — 文档的头标签
document.body — 文档的body标签;
document.documentElement — 文档的html标签;html标签并不是通过document.html去访问的;

json的遍历

//json
var json = {"aaa":11,"bbb":22};
//遍历
for(var k in json){
    console.log(k); //属性
    console.log(json[k]); //值
}

//compatMode属性,CSS1Compat
alert(document.compatMode);

//获取key为aaa的值
alert(json.aaa);

Scroll()的封装

判断页面有没有DTD约束:

document.compatMode === "BackCompat"
BackCompat  未声明
CSS1Compat  已经声明
// 封装scroll
function scroll() {  
    if(window.pageYOffset != null) {  // ie9+ 高版本浏览器
        // 因为 window.pageYOffset 默认的是  0  所以这里需要判断
        return {
            left: window.pageXOffset,
            top: window.pageYOffset
        }
    }
    else if(document.compatMode === "CSS1Compat") {    // 标准浏览器   来判断有没有声明DTD
        return {
            left: document.documentElement.scrollLeft,
            top: document.documentElement.scrollTop
        }
    }
    return {   // 未声明 DTD
        left: document.body.scrollLeft,
        top: document.body.scrollTop
    }
}
function scroll(){
    //简单封装
    return {
        "top": window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop,
        "left":  window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft
    }
}

ScrollTo

window.scrollTo ,屏幕跳转,方法可把内容滚动到指定的坐标。
语法:
scrollTo(xpos,ypos)
xpos 必需,要在窗口文档显示区左上角显示的文档的 x 坐标。
ypos 必需,要在窗口文档显示区左上角显示的文档的 y 坐标。

案例

案例一
需求:1、当我们滚动界面的时候,被卷曲的头部超过第二个盒子距离顶部的位置,那么直接给第二个盒子加类名.fixed;2、当我们滚动界面的时候,被卷曲的头部小于第二个盒子距离顶部的位置,那么直接给第二个盒子取消类名.fixed

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0
        }
        img {
            vertical-align: top;
        }
        .main {
            margin: 0 auto;
            width: 1000px;
            margin-top: 10px;
        }
        #Q-nav1 {
            overflow: hidden;
        }
        .fixed {
            position: fixed;
            top: 0;
            left: 0;
        }
    </style>
    <!--引入工具js-->
    <script src="my.js"></script>
    <script>
        window.onload = function () {

            //1.获取对象
            var topDiv = document.getElementById("top");
            var height = topDiv.offsetHeight;
            var middle = document.getElementById("Q-nav1");
            var main = document.getElementById("main");

            //2.卷起
            window.onscroll = function () {
                //判断被卷起的头部的大小
                if(scroll().top > height){
                    //3.满足条件添加类,否则删除类
                    middle.className += " fixed";
                    //第二个盒子不占位置,给第三个盒子一个上padding占位置,不出现盒子抖动问题
                    main.style.paddingTop = middle.offsetHeight + "px";
                }else {
                    middle.className = "";
                    //清零
                    main.style.paddingTop = 0;
                }
            }
        }
    </script>
</head>
<body>
    <div class="top" id="top">
        <img src="images/top.png" alt=""/>
    </div>
    <div id="Q-nav1">
        <img src="images/nav.png" alt=""/>
    </div>
    <div class="main" id="main">
        <img src="images/main.png" alt=""/>
    </div>
</body>
</html>

案例二
需求:屏幕滚动多少,两侧的图片联动向下移动等距离。

window.onload = function () {
    var imgArr = document.getElementsByTagName("img");
    window.onscroll = function () {
        //获取被卷去的头部的值
        var val = scroll().top;
        //移动两个盒子(缓动移动)
        animate(imgArr[0],val+80); //80是图片的高度
        animate(imgArr[1],val+80);
    }
}

案例三
需求:浏览器被卷去的头部超过1000显示小火箭,然后点击小火箭屏幕缓慢移动到最顶端。

window.onload = function () {
    //1.获取图片
    var img = document.getElementsByTagName("img")[0];
    window.onscroll = function () {
        //被卷去的距离大于1000显示小火箭,否则隐藏
        2.显示隐藏小火箭
        if(scroll().top>1000){
            img.style.display = "block";
        }else{
            img.style.display = "none";
        }
        //每次移动滚动条的时候都给leader赋值,模拟leader获取距离顶部的距离
        leader = scroll().top;
    }
    //3.缓动跳转到页面最顶端(利用我们的缓动动画)
    var timer = null;
    var target = 0; //目标位置
    var leader = 0; //显示区域自身的位置
    img.onclick = function () {
        //要用定时器,先清定时器
        clearInterval(timer);
        timer = setInterval(function () {
            //获取步长
            var step = (target-leader)/10;
            //处理步长
            step = step>0?Math.ceil(step):Math.floor(step);
            leader = leader +step;
            //显示区域移动
            // window.scrollTo(x,y);浏览器显示区域跳转到指定的坐标
            window.scrollTo(0,leader);
            //清除定时器
            if(leader === 0){
                clearInterval(timer);
            }
        },25);
    }
}

案例4
需求:点击ol中的li,屏幕滑动到对应的ul中的li的范围。
技术点:
盒子属性:auto:适应盒子自身的宽度或者高度。
盒子属性:100%:适应盒子父盒子的宽度或者高度。
100%子盒子会继承父盒子的宽高。父盒子继承body宽高。Body继承html的宽高。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        body,html {
            height: 100%;
        }
        ul {
            list-style: none;
            height: 100%;
        }
        ul li {
            height: 100%;
        }
        ol {
            list-style: none;
            position: fixed;
            top: 80px;
            left: 50px;
        }
        ol li {
            width: 50px;
            height: 50px;
            border: 1px solid #000;
            text-align: center;
            line-height: 50px;
            margin-top: -1px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <ul>
        <li>鞋子区域</li>
        <li>袜子区域</li>
        <li>裤子区域</li>
        <li>裙子区域</li>
        <li>帽子区域</li>
    </ul>
    <ol>
        <li>鞋子</li>
        <li>袜子</li>
        <li>裤子</li>
        <li>裙子</li>
        <li>帽子</li>
    </ol>
    <script src="animate.js"></script>
    <script>
        //0.获取元素
        var ul = document.getElementsByTagName("ul")[0];
        var ol = document.getElementsByTagName("ol")[0];
        var ulLiArr = ul.children;
        var olLiArr = ol.children;
        var target = 0;var leader = 0;var timer = null;
        //1.指定ul和ol中的li的背景色,对应的li背景色相同
        //设置一个数组,里面装颜色,然指定的颜色给数组中的指定元素
        var arrColor = ["pink","blue","yellow","orange","green"];
        //利用for循环给两个数组的元素上色
        for(var i=0;i<arrColor.length;i++){
            //上色
            ulLiArr[i].style.backgroundColor = arrColor[i];
            olLiArr[i].style.backgroundColor = arrColor[i];

            //属性绑定索引值
            olLiArr[i].index = i;
            //2.老三步。(并绑定事件)循环绑定,为每一个li绑定点击事件
            olLiArr[i].onclick = function () {
                //***获取目标位置
                    //获取索引值。
                target = ulLiArr[this.index].offsetTop;

                //要用定时器,先清除定时器
                clearInterval(timer);
                //3.利用缓动动画原理实现屏幕滑动
                timer = setInterval(function () {
                    //(1).获取步长
                    var step = (target-leader)/10;
                    //(2).二次处理步长
                    step = step>0?Math.ceil(step):Math.floor(step);
                    //(3).屏幕滑动
                    leader = leader + step;
                    window.scrollTo(0,leader);
                    //(4).清除定时器
                    if(Math.abs(target-leader)<=Math.abs(step)){
                        window.scrollTo(0,target);
                        clearInterval(timer);
                    }
                },25);
            }
        }

        //4.用scroll事件模拟盒子距离最顶端的距离。
        window.onscroll = function () {
            //每次屏幕滑动,把屏幕卷去的头部赋值给leader,模拟获取显示区域距离顶部的距离
            leader = scroll().top;
        }

    </script>
</body>
</html>

事件对象(event)

再触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。所有浏览器都支持event对象,但支持的方式不同。普通浏览器支持 event(带参,任意参数),ie 678 支持 window.event(无参,内置)。

事件对象的获取(event的获取)

IE678中,window.event,在火狐谷歌中,event或者,在事件绑定的函数中,加参,这个参数就是event。

获取事件的兼容方式

  • 不写参数直接使用event;
  • 写参数,但是为event….var,(主要用这种)
event  = event || window.event;

事件属性

screenX、pageX和clientX的区别

  • PageY/pageX: 鼠标位于整个网页页面的顶部和左侧部分的距离。(页面)
  • ScreenY/screenX: 鼠标位于屏幕的上方和左侧的距离。(屏幕)
  • ClientX/clientY: 鼠标位于浏览器的左侧和顶部的距离。(浏览器大小和位置)

PageY和pageX的兼容写法

在页面位置就等于 = 看得见的+看不见的

pageY/pageX=event.clientY/clientX+scroll().top/scroll().left

onmousemove

onmousemove事件会在鼠标指针移动时发生。

案例

1、需求:当鼠标进入图片,出现细节图。鼠标放到小盒子上,让大盒子里面的图片和我们同步等比例移动。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            width: 350px;
            height: 350px;
            margin:100px;
            border: 1px solid #ccc;
            position: relative;
        }
        .big {
            width: 400px;
            height: 400px;
            position: absolute;
            top: 0;
            left: 360px;
            border: 1px solid #ccc;
            overflow: hidden;
            display: none;
        }
        .mask {
            width: 175px;
            height: 175px;
            background: rgba(255, 255, 0, 0.4);
            position: absolute;
            top: 0;
            left: 0;
            cursor: move;
            display: none;
        }
        .small {
            position: relative;
        }
        img {
            vertical-align: top;
        }
    </style>
    <script src="animate.js"></script>
    <script>
        window.onload = function () {
            //技术点:onmouseenter==onmouseover 前者不支持冒泡
            //技术点:onmouseleave==onmouseout  前者不支持冒泡      

            //0.获取相关元素
            var box = document.getElementsByClassName("box")[0];
            var small = box.firstElementChild || box.firstChild;
            var big = box.children[1];
            var mask = small.children[1];
            var bigImg = big.children[0];

            //1.鼠标放上去显示盒子,移开隐藏盒子。(为小盒子绑定事件)
            small.onmouseenter = function () {
                //封装好方法调用:显示元素
                show(mask);
                show(big);
            }
            small.onmouseleave = function () {
                //封装好方法调用:隐藏元素
                hide(mask);
                hide(big);
            }

            //2.黄盒子跟随移动
            //绑定的事件是onmousemove,而事件源是small(只要在小盒子上移动1像素,黄盒子也要跟随)
            small.onmousemove = function (event) {
                //想移动黄盒子,必须知道鼠标在small中的位置。x作为mask的left值,y作mask的top值。

                event = event || window.event;
                var pagex = event.pageX || scroll().left + event.clientX;
                var pagey = event.pageY || scroll().top + event.clientY;
                //让鼠标在黄盒子最中间,减去黄盒子宽高的一半
                var x = pagex - box.offsetLeft - mask.offsetWidth/2;
                var y = pagey - box.offsetTop - mask.offsetHeight/2;
                //限制换盒子的范围
                //left取值为大于0,小盒子的宽-mask的宽。
                if(x<0){
                    x = 0;
                }
                if(x>small.offsetWidth-mask.offsetWidth){
                    x = small.offsetWidth-mask.offsetWidth;
                }
                //top同理。
                if(y<0){
                    y = 0;
                }
                if(y>small.offsetHeight-mask.offsetHeight){
                    y = small.offsetHeight-mask.offsetHeight;
                }
                //移动黄盒子
                console.log(small.offsetHeight);
                mask.style.left = x + "px";
                mask.style.top = y + "px";

                //3.右侧的大图片,等比例移动。
                //如何移动大图片?等比例移动。
                //    大图片/大盒子 = 小图片/mask盒子
                //    大图片走的距离/mask走的距离 = (大图片-大盒子)/(小图片-黄盒子)
//              var bili = (bigImg.offsetWidth-big.offsetWidth)/(small.offsetWidth-mask.offsetWidth);

                //大图片走的距离/mask盒子都的距离 = 大图片/小图片
                var bili = bigImg.offsetWidth/small.offsetWidth;

                var xx = bili*x;
                var yy = bili*y;

                bigImg.style.marginTop = -yy+"px";
                bigImg.style.marginLeft = -xx+"px";
            }

        }
    </script>
</head>
<body>
    <div class="box">
        <div class="small">
            <img src="images/001.jpg" alt=""/>
            <div class="mask"></div>
        </div>
        <div class="big">
            <img src="images/0001.jpg" alt=""/>
        </div>
    </div>
</body>
</html>

2、需求:在指定位置按住鼠标左键移动对话框。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .nav {
            height: 30px;
            background: #036663;
            border-bottom: 1px solid #369;
            line-height: 30px;
            padding-left: 30px;
        }

        .nav a {
            color: #fff;
            text-align: center;
            font-size: 14px;
            text-decoration: none;

        }

        .d-box {
            width: 400px;
            height: 300px;
            border: 5px solid #eee;
            box-shadow: 2px 2px 2px 2px #666;
            position: absolute;
            top: 40%;
            left: 40%;
        }

        .hd {
            width: 100%;
            height: 25px;
            background-color: #7c9299;
            border-bottom: 1px solid #369;
            line-height: 25px;
            color: white;
            cursor: move;
        }

        #box_close {
            float: right;
            cursor: pointer;
        }
    </style>

    <script src="animate.js"></script>
    <script>
        window.onload = function () {
            //分析:鼠标按下,触动事件,移动在更换对话框的位置。
            //鼠标按下onmousedown   鼠标弹起:onmouseup   鼠标移动onmousemove

            var box = document.getElementById("d_box");
            var drop = document.getElementById("drop");
            //先按下,在移动触动此事件
            drop.onmousedown = function (event) {
                //获取鼠标在盒子中的坐标,将来移动的时候减去保证鼠标在盒子的指定位置
                event = event || window.event;
                var pagex = event.pageX || scroll().left + event.clientX;
                var pagey = event.pageY || scroll().top + event.clientY;
                var x = pagex - box.offsetLeft;
                var y = pagey - box.offsetTop;


                document.onmousemove = function (event) {
                    //2.把鼠标的坐标赋值给对话框。
                    event = event || window.event;
                    var xx = event.pageX || scroll().left + event.clientX;
                    var yy = event.pageY || scroll().top + event.clientY;
                    //二次操作鼠标位置  减去鼠标在盒子中的坐标
                    xx = xx - x;
                    yy = yy - y;

                    //给box赋值
                    box.style.left = xx+"px";
                    box.style.top = yy+"px";
                    //禁止文本选中(选中后取消)
                    window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
                }
            }

            //事件解绑
            drop.onmouseup = function () {
                //解绑
                document.onmousemove = null;
            }
        }
    </script>

</head>
<body>
    <!--顶部注册部分,无用-->
    <div class="nav">
        <a href="javascript:;" id="register">注册信息</a>
    </div>
    <!--我们移动的对话框-->
    <div class="d-box" id="d_box">
        <div class="hd" id="drop">
            <i>注册信息 (可以拖拽)</i>
            <span id="box_close">【关闭】</span>
        </div>
        <div class="bd"></div>
    </div>

</body>
</html>

3、需求:模拟滚动条,鼠标拖动滚动条,滚动条动,而且内容等比例联动。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            width: 300px;
            height: 500px;
            border: 1px solid red;
            margin: 50px auto;
            overflow: hidden;
            position: relative;
        }
        .scroll {
            width: 20px;
            height: 530px;
            background-color: #ccc;
            position: absolute;
            top: 0;
            right: 0;
        }
        .bar {
            width: 20px;
            background-color: red;
            border-radius: 10px;
            cursor: pointer;
            position: absolute;
            top: 0;
        }
        .content {
            padding: 15px;
        }
    </style>

    <script src="animate.js"></script>
    <script>
        window.onload = function () {
            //步骤:
            //1.根据内容和盒子的比例确定bar的高。
            //2.绑定事件(鼠标按下,然后移动)
            //3.鼠标移动,bar联动
            //4.内容等比例联动

            //0.获取相关元素
            var box = document.getElementById("box");
            var content = box.children[0];
            var scroll = box.children[1];
            var bar = scroll.children[0];

            //1.根据内容和盒子的比例确定bar的高。
            //内容的高/盒子的高 = scroll的高/bar的高
            //bar的高 = 盒子的高*scroll的高/内容的高
            var barHeight = box.offsetHeight*scroll.offsetHeight/content.offsetHeight;
            bar.style.height = barHeight + "px";
            //2.绑定事件(鼠标按下,然后移动)
            bar.onmousedown = function (event) {
                event = event || window.event;
                var pageyy = event.pageY || scroll().top + event.clientY;
                var y = pageyy - bar.offsetTop;
                //模拟拖拽案例
                document.onmousemove = function (event) {
                    //获取鼠标在页面的位置。
                    event = event || window.event;
                    var pagey = event.pageY || scroll().top + event.clientY;
                    //鼠标的位置-鼠标在盒子中的位置。
                    pagey = pagey - y;
                    //限制y的取值。大于0,小于scroll的高度-bar的高度
                    if(pagey<0){
                        pagey = 0;
                    }
                    if(pagey>scroll.offsetHeight-bar.offsetHeight){
                        pagey = scroll.offsetHeight-bar.offsetHeight;
                    }

                    //3.鼠标移动,bar联动
                    bar.style.top = pagey + "px";

                    //4.内容等比例联动
                    //高级比例:  内容走的距离/bar走的距离 = (内容的高-大盒子的高)/(scroll的高-bar的高)
                    var s = pagey *(content.offsetHeight-box.offsetHeight)/(scroll.offsetHeight-bar.offsetHeight);
                    //s赋值给content。通过marginTop负值移动content
                    content.style.marginTop = -s+"px";

                    //让被选文字清除。
                    window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
                }
            }

            //事件解绑
            document.onmouseup = function () {
                document.onmousemove = null;
            }
        }
    </script>

</head>
<body>
    <div class="box" id="box">
        <div class="content">
           JavaScript脚本语言具有以下特点:<br>
            (1)脚本语言。JavaScript是一种解释型的脚本语言,C、C++等语言先编译后执行,而JavaScript是在程序的运行过程中逐行进行解释。<br>
            (2)基于对象。JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象。<br>
            (3)简单。JavaScript语言中采用的是弱类型的变量类型,对使用的数据类型未做出严格的要求,是基于Java基本语句和控制的脚本语言,其设计简单紧凑。<br>
            (4)动态性。JavaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应。在访问一个网页时,鼠标在网页中进行鼠标点击或上下移、窗口移动等操作JavaScript都可直接对这些事件给出相应的响应。<br>
            (5)跨平台性。JavaScript脚本语言不依赖于操作系统,仅需要浏览器的支持。因此一个JavaScript脚本在编写后可以带到任意机器上使用,前提上机器上的浏览器支 持JavaScript脚本语言,目前JavaScript已被大多数的浏览器所支持。<br>
            不同于服务器端脚本语言,例如PHP与ASP,JavaScript主要被作为客户端脚本语言在用户的浏览器上运行,不需要服务器的支持。所以在早期程序员比较青睐于JavaScript以减少对服务器的负担,而与此同时也带来另一个问题:安全性。
            而随着服务器的强壮,虽然程序员更喜欢运行于服务端的脚本以保证安全,但JavaScript仍然以其跨平台、容易上手等优势大行其道。同时,有些特殊功能(如AJAX)必须依赖Javascript在客户端进行支持。随着引擎如V8和框架如Node.js的发展,及其事件驱动及异步IO等特性,JavaScript逐渐被用来编写服务器端程序。<br>
        </div>
        <div class="scroll">
            <div class="bar"></div>
        </div>
    </div>
</body>
</html>

Client

clientWidth & clientHeight

clientWidth 获取网页可视区域宽度
clientHeight 获取网页可视区域高度
两种用法,调用者不同,意义不同:
- 盒子调用: 指盒子本身。
- body/html调用: 可视区域大小。

clientX & clientY

clientX 鼠标距离可视区域左侧距离(event调用)
clientY 鼠标距离可视区域上侧距离(event调用)

clientTop & clientLeft

clientTop和clientLeft分别表示盒子的border宽和高。

Offset、ScrollTo、Client 总结

Width和height

  • clientWidth = width + padding
  • clientHeight = height + padding
  • offsetWidth = width + padding + border
  • offsetHeight = height + padding + border
  • scrollWidth = 内容宽度(不包含border)
  • scrollHeight = 内容高度(不包含border)

top和left

  • offsetTop/offsetLeft :
    • 调用者:任意元素。(盒子为主)
    • 作用:距离父系盒子中带有定位的距离。
  • scrollTop/scrollLeft:(盒子也可以调用,必须有滚动条)
    • 调用者:document.body.scrollTop/…..(window)
    • 作用:浏览器无法显示的部分(被卷去的部分)。
  • clientY/clientX:(clientTop/clientLeft 值的是border)
    • 调用者:event.clientX(event)
    • 作用:鼠标距离浏览器可视区域的距离(左、上)。

Client检浏览器宽/高度(可视区域)

//获取屏幕可视区域的宽高
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
        }
    }
}

Onresize事件

浏览器的大小改变时触发。

事件总结

区分:
1. window.onscroll 屏幕滑动
2. window.onresize 浏览器大小变化
3. window.onload 页面加载完毕
4. div.onmousemove 鼠标在盒子上移动
5. onmouseup/onmousedown == onclick

获得屏幕宽高

分辨率是屏幕图像的精密度,指显示器所能显示的像素有多少。

window.screen.width

冒泡

事件冒泡: 当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;这个事件从原始元素开始一直冒泡到DOM树的最上层。
冒泡:子元素事件被触动,父盒子的同样的事件也会被触动。
取消冒泡就是取消这种机制。

阻止冒泡

  • w3c的方法是:(火狐、谷歌、IE11)
event.stopPropagation()
  • IE10以下则是使用:
event.cancelBubble = true

兼容写法

    //阻止冒泡
    event = event || window.event;

    if(event && event.stopPropagation){
        event.stopPropagation();
    }else{
        event.cancelBubble = true;
    }

addEventListenner

addEventListenner(参数1,参数2,参数3)方法用来绑定事件。
- 调用者是:事件源。
- 参数1:事件去掉on
- 参数2 :调用的函数
- 参数3:可有可无。没有默认false.false情况下,支持冒泡。True支持捕获。

案例

1、需求:点击登录按钮,显示模态框。点击出去login以外的所有盒子隐藏模态框。

<!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>
        //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.target:event.srcElement;
            console.log(event.target);
            //判断目标值的ID是否等于login,如果等于不隐藏盒子,否则隐藏盒子。
            if(aaa.id !== "login"){
                mask.style.display = "none";
            }
        }
    </script>
</body>
</html>

事件委托

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

//普通的事件绑定,没有办法为新创建的元素绑定事件。所以我们要使用冒泡的特性,事件委托
ul.onclick = function (event) {
    //获取事件触动的时候传递过来的值
    event = event || window.event;
    var aaa = event.target?event.target:event.srcElement;
    //判断标签名,如果是li标签弹窗
    if(aaa.tagName === "LI"){
        alert("我是li");
    }
}

缓动框架

获取任意类型的CSS样式的属性值

Div.style.width
div.currentStyle.width
Window.getComputedStyle(div,null).width;
他们的公共使用变量或者字符串获取属性值的方法都是:去电属性和点,然后加上中括号和属性的字符串形式。

var div = document.getElementsByTagName("div")[0];
console.log(getStyle(div,"padding"));
console.log(getStyle(div,"background-color"));
//兼容方法获取元素样式
function getStyle(ele,attr){
    if(window.getComputedStyle){
        return window.getComputedStyle(ele,null)[attr];
    }
    return ele.currentStyle[attr];
}

开闭原则

定义一个变量。数据可以修改。但是,只能修改成为两个值。

<!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 json = {"left":10,"top":200,"width":300,"height":200};
            animate(div,json);
        }

        //参数变为3个
        function animate(ele,json){
            //先清定时器
            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;
                    }
                }
                //只有所有的属性都到了指定位置,bool值才不会变成false;
                if(bool){
                    clearInterval(ele.timer);
                }
            },25);
        }

        //兼容方法获取元素样式
        function getStyle(ele,attr){
            if(window.getComputedStyle){
                return window.getComputedStyle(ele,null)[attr];
            }
            return ele.currentStyle[attr];
        }
    </script>
</body>
</html>

回调函数

程序执行完毕,在次执行的函数。
在函数中给指定的函数定义一个形参,然后程序执行到最后,调用这个形参后面加一个括号。

<!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, function () {
                    animate(div,json1);
                });
            });
        }

        //参数变为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;
                    }
                }
                //只有所有的属性都到了指定位置,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>

案例

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>旋转木马轮播图</title>
    <link rel="stylesheet" href="css/css.css"/>
    <script src="js/jquery1.0.0.1.js"></script>
    <script src="js/js.js"></script>
</head>
<body>

    <div class="wrap" id="wrap">
       <div class="slide" id="slide">
           <ul>
               <!--五张图片-->
               <li><a href="#"><img src="images/slidepic1.jpg" alt=""/></a></li>
               <li><a href="#"><img src="images/slidepic2.jpg" alt=""/></a></li>
               <li><a href="#"><img src="images/slidepic3.jpg" alt=""/></a></li>
               <li><a href="#"><img src="images/slidepic4.jpg" alt=""/></a></li>
               <li><a href="#"><img src="images/slidepic5.jpg" alt=""/></a></li>
           </ul>
           <!--左右切换按钮-->
           <div class="arrow" id="arrow">
               <a href="javascript:;" class="prev"></a>
               <a href="javascript:;" class="next"></a>
           </div>
       </div>
    </div>
</body>
</html>
window.onload = function () {
    var arr = [
        {   //  1
            width:400,
            top:70,
            left:50,
            opacity:20,
            zIndex:2
        },
        {  // 2
            width:600,
            top:120,
            left:0,
            opacity:80,
            zIndex:3
        },
        {   // 3
            width:800,
            top:100,
            left:200,
            opacity:100,
            zIndex:4
        },
        {  // 4
            width:600,
            top:120,
            left:600,
            opacity:80,
            zIndex:3
        },
        {   //5
            width:400,
            top:70,
            left:750,
            opacity:20,
            zIndex:2
        }
    ];

    //0.获取元素
    var slide = document.getElementById("slide");
    var liArr = slide.getElementsByTagName("li");
    var arrow = slide.children[1];
    var arrowChildren = arrow.children;
    //设置一个开闭原则变量,点击以后修改这个值。
    var flag = true;

    //1.鼠标放到轮播图上,两侧的按钮显示,移开隐藏。
    slide.onmouseenter = function () {
        //arrow.style.opacity = 1;
        animate(arrow,{"opacity":100});
    }
    slide.onmouseleave = function () {
        //arrow.style.opacity = 1;
        animate(arrow,{"opacity":0});
    }

    move();
    //3.把两侧按钮绑定事件。(调用同一个方法,只有一个参数,true为正向旋转,false为反向旋转)
    arrowChildren[0].onclick = function () {
        if(flag){
            flag = false;
            move(true);
        }
    }
    arrowChildren[1].onclick = function () {
        if(flag){
            flag = false;
            move(false);
        }
    }

    //4.move函数
    function move(bool){
        //判断:如果等于undefined,那么就不执行这两个if语句
        if(bool === true || bool === false){
            if(bool){
                arr.unshift(arr.pop());
            }else{
                arr.push(arr.shift());
            }
        }
        //在次为页面上的所有li赋值属性,利用缓动框架
        for(var i=0;i<liArr.length;i++){
            animate(liArr[i],arr[i], function () {
                flag = true;
            });
        }
    }

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值