12_JS的client家族、事件冒泡机制、动画原理、匀速动画的封装

client 家族

client 可视区域
offsetWidth: width + padding + border (披着羊皮的狼)
clientWidth: width + padding 不包含border
scrollWidth:大小是内容的大小,
注意:即使使用overflow:hiddenscrollWidth也不会变小

检测浏览器可视区域的大小

  • IE9及其以上的版本
    window.innerWidth
  • 标准模式(等于CSS1Compat
    document.documentElement.clientWidth
  • 怪异模式
    document.body.clientWidth

获取可视区域大小的函数封装

<script type="text/javascript">
        function client(){
            if(window.innerWidth != null){
                return {
                    width:window.innerWidth,
                    height:window.innerHeight
                }
            }else if(document.compatMode == "CSS1Compat"){
                return {
                    width:document.documentElement.clientWidth,
                    height:document.documentElement.clientHeight
                }
            }
            return {
                width:document.body.clientWidth,
                height:document.body.clientHeight
            }
        }
        document.write(client().width+":"+client().height);
    </script>

window.onresize改变窗口事件

昨天 window.onscroll = function() {} 屏幕滚动事件
今天 window.onresize = function() {} 窗口改变事件
onresize 事件会在窗口或框架被调整大小时发生

区分:

  • window.onscroll 屏幕滑动
  • window.onresize 浏览器大小变化
  • window.onload 页面加载完毕
  • div.onmousemove 鼠标在盒子上移动

例:根据屏幕大小改变页面颜色

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript">
        function client(){
            if(window.innerWidth != null){
                return {
                    width:window.innerWidth,
                    height:window.innerHeight
                }
            }else if(document.compatMode == "CSS1Compat"){
                return {
                    width:document.documentElement.clientWidth,
                    height:document.documentElement.clientHeight
                }
            }
            return {
                width:document.body.clientWidth,
                height:document.body.clientHeight
            }
        }
        window.onload = function () {
            MyResize();
            window.onresize = MyResize;
            function MyResize(){
                var w = client().width;
                if(w>960){
                    document.body.style.backgroundColor = "red";
                }else if(w>640){
                    document.body.style.backgroundColor = "green";
                }else{
                    document.body.style.backgroundColor = "blue";
                }
            }
        }
    </script>
</head>
<body>

</body>
</html>

window.screen.width检测屏幕宽度(分辨率)

返回的是我们电脑的屏幕的分辨率 , 跟浏览器没有关系
分辨率:是屏幕图像的精密度,指显示器所能显示的像素有多少。

冒泡机制(event)

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

事件传播的三个阶段

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

冒泡顺序

  • IE 6.0:
    div -> body -> html -> document

  • 其他浏览器:
    div -> body -> html -> document -> window

  • 不是所有的事件都能冒泡, 以下事件不冒泡:blur、focus、load、unload、onmouseenter onmouseleave

阻止冒泡

标准浏览器 和 IE浏览器
标准浏览器指的是:IE9+和其他浏览器
IE浏览器指的是:IE6、7、8
w3c的方法是event.stopPropagation() Propagation 传播 传递
IE则是使用event.cancelBubble = true bubble 冒泡 泡泡 cancel 取消

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript">
        window.onload = function () {
            var btn = document.getElementsByTagName("button")[0];
            document.onclick = function () {
                alert("空白处点击");
            }
            btn.onclick = function (event) {
                alert("按钮点击");
                var event = event||window.event;
                if(event && event.stopPropagation){
                    event.stopPropagation();
                }else{
                    event.cancelBubble = true;
                }
            }
        }
    </script>
</head>
<body>
    <button>点击</button>
</body>
</html>

判断当前对象

火狐、谷歌、等 : event.target
IE 6、7、8:event.srcElement
兼容性写法获取元素ID:

var event = event || window.event;
var targetId = event.target ? event.target.id : event.srcElement.id;

targetId == "show"来判断当前点击是否点中了id=show的元素

例:点击空白处,弹出框消失
  这个案例就是说,一个盒子,点击除了自己之外的任何一个地方,就会隐藏。
原理:
  点击自己不算 ( 怎么证明我是我 点击的这个对象id 正好和自己一样 )
  点击空白处 就是点击 document

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        body{
            height: 1000px;
        }
        .nav{
            width: 100%;
            height: 42px;
            background-color: #2006ac;
        }
        a{
            text-decoration: none;
            color: #fff;
            line-height: 42px;
            margin-left: 12px;
        }
        .mask{
            width: 100%;
            height: 100%;
            opacity: 0.4;
            filter:alpha(opacity=40);
            background-color: #000;
            position: fixed;
            left: 0;
            top: 0;
            display: none;
        }
        .show{
            width: 400px;
            height: 300px;
            background-color: #fff;
            position: fixed;
            left: 50%;
            top: 50%;
            margin-left: -200px;
            margin-top: -150px;
            display: none;
        }
    </style>
    <script type="text/javascript">
        function $(id){return document.getElementById(id);}
        window.onload = function () {
            var btn = $("register");
            btn.onclick = function (event) {
                $("mask").style.display = "block";
                $("show").style.display = "block";
                document.body.style.overflow = "hidden";  // 不显示滚动条
                var event = event||window.event;
                if(event && event.stopPropagation){//阻止事件冒泡
                    event.stopPropagation();
                }else{
                    event.cancelBubble = true;
                }
            }
            document.onclick = function (event) {//点击空白处消失
                var event = event||window.event;
                var tid = event.target?event.target.id:event.srcElement.id;
                if(tid != "show"){//点击的不是弹出框
                    $("mask").style.display = "none";
                    $("show").style.display = "none";
                    document.body.style.overflow = "visible";  // 显示滚动条
                }
            }
        }
    </script>
</head>
<body>
    <div class="nav">
        <a href="javascript:;" id="register">注册</a>
        <a href="javascript:;">登录</a>
    </div>
    <div class="mask" id="mask"></div>
    <div class="show" id="show"></div>
</body>
</html>

例:选中之后,弹出层
我们想,选中某些文字之后,会弹出一个弹出框,这个和我们前面讲过的拖拽有点不一样。
拖拽是拖着走。 拉着鼠标走 。选择文字: 这个弹出的层 选中的时候不出来,弹起鼠标的时候才出现 。
所以这个的事件一定是 onmouseup . 盒子显示而且盒子的位置 再 鼠标的 clientX 和 clientY 一模一样

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        .box{
            width: 500px;
        }
        .demo{
            width: 100px;
            background-color: pink;
            position: absolute;
            left: 0;
            top: 0;

        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            var box = document.getElementById("box");
            var demo = document.getElementById("demo");
            box.onmouseup = function (event) {
                var event = event||window.event;
                var left = event.clientX;
                var top = event.clientY;

                var txt;//被选中的文字
                if(window.getSelection){
                    txt = window.getSelection().toString();
                }else{
                    txt = document.selection.createRange().text;
                }
                if(txt){
//                    console.dir(txt);
                    showBox(txt,left,top);
                }
            }
            function showBox(txt,left,top){
                setTimeout(function () {
                    demo.style.display = "block";
                    demo.innerHTML = txt;
                    demo.style.left = left+"px";
                    demo.style.top = top+"px";
                },200);

            }
            function hideBox(){
                demo.style.display = "none";
            }
            document.onmousedown = function (event) {//点击空白处
                var event = event||window.event;
                var targetId = event.target?event.target.id:event.srcElement.id;
                if(targetId != "demo"){
                    hideBox();
                }
            }
        }
    </script>
</head>
<body>
    <div class="box" id="box">
        演唱:张学友
        曲 :戚小恋 词 :姚若龙 编 :屠颖
        你瘦了憔悴的让我好心疼
        有时候爱情比时间还残忍
        有人变得盲目
        而奋不顾身
        忘了爱 爱两个同样 用心的人
        你醉了脆弱得藏不住泪痕
        我知道绝望比冬天还寒冷
        你恨自己是个
        怕孤独的人
        偏偏又爱上自由自私的灵魂
        你带着他唯一写过的情书
        想证明当初爱得并不糊涂
        他曾为了你的逃离颓废痛苦
        也为了破镜重圆抱着你哭
        哦 ~ 可惜爱不是几滴眼泪几封情书
        哦 ~ 这样的话或许有点残酷
        等待着别人给幸福的人
        往往过得都不怎麽幸福
        哦 ~ 可惜爱不是忍着眼泪留着情书
        哦 ~ 伤口清醒要比昏迷痛楚
        紧闭着双眼 又拖着错误
        真爱 来临时你又要怎麽 留得住
    </div>
    <div class="demo" id="demo"></div>
</body>
</html>

动画

动画的原理就是:

盒子本身的位置+步长
盒子offsetLeft+步长

btn.onclick = function()
{
    //最基本的运动
    setInterval('move(box)',30);
}

运动的数学公式: s=s+s'

  • 最初级的匀速运动
function move(obj){
    obj.style.left=obj.offsetLeft+speed+'px';
}
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>动画基本原理</title>
    <style type="text/css">
        .box{
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
            left: 8px;
            top: 100px;
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            var btn = document.getElementsByTagName("button")[0];
            var box = document.getElementById("box");
            var timer = null;
            btn.onclick = function () {
                timer = setInterval(function () {
                    if(box.offsetLeft > 600) clearInterval(timer);
                    box.style.left = box.offsetLeft+10+"px";
                },20);
            }
        }
    </script>
</head>
<body>
    <button>开始</button>
    <div class="box" id="box"></div>
</body>
</html>

例:动画函数的初步封装

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        div{
            width: 100px;
            height: 100px;
            position: absolute;
            background-color: pink;
        }
    </style>
    <script type="text/javascript">
        function $(id){return document.getElementById(id);}
        window.onload = function () {
            var box = $("box");
            $("btn400").onclick = function () {
                animate(box,400);
            }
            $("btn800").onclick = function () {
                animate(box,800);
            }

            function animate(obj,target){
                obj.timer = setInterval(function () {
                    if(obj.offsetLeft>=target) clearInterval(obj.timer);
                    obj.style.left = obj.offsetLeft+10+"px";
                },20);
            }
        }
    </script>
</head>
<body>
    <button id="btn400">400</button>
    <button id="btn800">800</button>
    <div id="box"></div>
</body>
</html>

例:匀速动画函数的封装完善

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        div{
            width: 100px;
            height: 100px;
            position: absolute;
            background-color: pink;
        }
        div#box1{
            top: 150px;
        }
    </style>
    <script type="text/javascript">
        function $(id){return document.getElementById(id);}
        window.onload = function () {
            var box = $("box");
            var box1 = $("box1");
            $("btn400").onclick = function () {
                animate(box,400);
                animate(box1,600);
            }
            $("btn800").onclick = function () {
                animate(box,800);
            }

            function animate(obj,target){
                clearInterval(obj.timer);
                var speed = obj.offsetLeft<target?5:-5;
                obj.timer = setInterval(function () {
                    var reslut = target - obj.offsetLeft;
                    obj.style.left = obj.offsetLeft+speed+"px";
                    if(Math.abs(reslut)<=5){
                        clearInterval(obj.timer);
                        obj.style.left = target;
                    }
                },20);
            }
        }
    </script>
</head>
<body>
<button id="btn400">400</button>
<button id="btn800">800</button>
<div id="box"></div>
<div id="box1"></div>
</body>
</html>

例:轮播图

  • 要实现无缝轮播,需要把第一张图片拷贝插入到最后面,当轮播到最后一张(也就是第一张图片)时,需要将盒子.style.left = 0;不能使用动画
  • 每隔一秒(一般是3秒,这里为了测试使用1秒)图片轮播一次
  • 鼠标放在放在序列号上,图片切换到当前序列号指向的位置
  • 鼠标放在图片上,停止轮播,鼠标移出图片,从原来位置继续轮播
  • 当图片轮播到4,鼠标放在序列号1时,当前显示第一张图片,当鼠标移开时,从第一张往后轮播而不是从第四张
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        ul,ol,li{
            list-style: none;
        }
        img{
            display: block;
        }
        .all{
            width: 500px;
            height: 200px;
            padding: 5px;
            border: 1px solid #999;
            margin: 100px auto;
            position: relative;
        }
        .screen{
            width: 500px;
            height: 200px;
            overflow: hidden;
            position: relative;
        }
        .screen ul{
            width: 1000%;
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
        }
        .screen li{
            float: left;
        }
        .all ol{
            position: absolute;
            right: 10px;
            bottom: 10px;

        }
        .all ol li{
            float: left;
            width: 18px;
            height: 18px;
            background-color: #fff;
            margin-right: 8px;
            text-align: center;
            line-height: 18px;
            border-radius: 9px;
        }
        .all li.current{
            background-color: pink;
            /*color: #ccc;*/
        }
    </style>
    <script type="text/javascript">
        function $(id){return document.getElementById(id);}
        function animte(obj , target){
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                var step = (target - obj.offsetLeft)/10;
                step = step>0?Math.ceil(step):Math.floor(step);
                obj.style.left = obj.offsetLeft+step+"px";
                if(obj.offsetLeft == target){
                    clearInterval(obj.timer);
                }
            },20);
        }

        window.onload = function () {
            var all = $("all");
            var ul = $("ul");

            var cloneOne = ul.children[0].cloneNode(true);
            ul.appendChild(cloneOne);

            var ulis = ul.children;

            //动态插入序列
            var ol = document.createElement("ol");
            ol.id = "ol";
            all.appendChild(ol);

            for(var i=0 ; i<ulis.length - 1 ; i++){//插入ol
                var li = document.createElement("li");
                li.innerHTML = i+1;
                ol.appendChild(li);
            }
            ol.children[0].className = "current";

            //鼠标移动到哪个就显示哪张图片
            var olis = $("ol").children;
            for(var i = 0 ; i<olis.length ;i++){
                var oli = olis[i];
                oli.index = i;
                oli.onmouseover  = function () {
                    for(var j = 0; j<ulis.length-1 ;j++){
                        olis[j].className = "";
                    }
                    this.className = "current";
                    //开始动画
                    animte(ul,-this.index*ulis[0].offsetWidth);
                    index =squece= this.index;
                }
            }
            //开启定时器,自动轮播
            var timer= null;
            var index = 0;
            var squece = 0;//当前的索引
            timer = setInterval(autoPlay,1000);
            function autoPlay() {
                index++;

                if(index>(ulis.length-1) ){
                    ul.style.left = 0;
                    index = 1;
                }
                //先清除所有的
                for(var i = 0;i<olis.length ; i++){
                    olis[i].className = "";
                }
                squece++;
                if(squece>olis.length-1){
                    squece = 0;
                }
//                console.dir(index);
                olis[squece].className = "current";

                animte(ul,-index*ulis[0].offsetWidth);
            }
            all.onmouseover = function () {
                clearInterval(timer);
            }
            all.onmouseout = function () {
                timer = setInterval(autoPlay,1000);
            }

        }
    </script>
</head>
<body>
    <div class="all" id="all">
        <div class="screen">
            <ul id="ul">
                <li><a href="#">![](images/1.jpg)</a></li>
                <li><a href="#">![](images/2.jpg)</a></li>
                <li><a href="#">![](images/3.jpg)</a></li>
                <li><a href="#">![](images/4.jpg)</a></li>
                <li><a href="#">![](images/5.jpg)</a></li>
            </ul>
        </div>

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

推荐阅读更多精彩内容

  • 以下文章为转载,对理解JavaScript中的事件处理机制很有帮助,浅显易懂,特分享于此。 什么是事件? 事件(E...
    jxyjxy阅读 3,022评论 1 10
  • offset家族三大家族和一个事件对象三大家族(offset/scroll/client)事件对象/event ...
    Yuann阅读 938评论 0 5
  • 事件流 IE和Netscape开发团队提出了完全相反的两种事件流的概念,事件冒泡流和事件捕获流。 事件冒泡 事件由...
    exialym阅读 920评论 0 9
  • 三大家族属性 client/scroll/offset clientLeft 表示当前标签距离左侧的 border...
    GodlinE阅读 296评论 0 2
  • 小时候,常喜欢听父亲讲故事,上古神话,朝代隐秘(其实是野史)。最让我震惊的是一夜白头的神秘。我害怕这种巨变出现在自...
    梭罗密阅读 275评论 2 1