楼层滚动

1更灵活的函数.png

之前写过动画函数

ani(box,"width",500,1000,function(a){})
//box的width增加(减少)到500,总用时1s,
//完成动画之后的回调为function(a){},运算的结果a传递到回调函数中。

但是这样的封装比较局限,只能是改变元素的style,而封装成increase这个样的函数,应用场景会多一点。

increase(200,500,1000,function(a){
  box.style.width=a+"px";
})
increase(0,1,1000,function(a){
  box.style.opacity=a;//不用单位
})
//这样也可以完成动画,而且更加灵活
1increase.png

可以将计时器返回出来,在计时器还没有结束之前提前清除计时器clearIntarval(t);

小练习:
五个按钮,点击之后变色,hover之后变色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div class="btn">
        <button>1</button>
        <button>2</button>
        <button>3</button>
        <button>4</button>
        <button>5</button>
    </div>
</body>
<script>
    var buttons=document.getElementsByTagName("button");
    var cur=0;
    buttons[0].style.backgroundColor="orange";
    for(var i=0;i<buttons.length;i++){
        buttons[i].index=i;
        buttons[i].onclick=function (){
            buttons[cur].style.backgroundColor="white";
            cur=this.index;
            buttons[cur].style.backgroundColor="orange";
        }
        buttons[i].onmouseover=function(){
            this.style.backgroundColor="orange";
        }
        buttons[i].onmouseout=function(){
//重要是这句
//点击按钮之后再mouseout就不能让他变白
            if(this.index!=cur){
                this.style.backgroundColor="white";
            }
        }
    }

</script>
</html>

楼层滚动:

注意,浏览器刷新时,滚动条是不会重置的,但是代码会重新执行,假如说用户滚动到第三层时刷新了,刷新后楼层还是在第三层,所以刷新后应该让代码先在网页加载时执行一遍,所以把监听的函数提取出来,先执行一遍。而且我们之前写的是距离浏览器窗口顶部100px以内才执行相关操作,而用户是停留在第三层并不满足这个条件。所以判断当前可视区域是哪一个楼层还需要将判别条件重新定义。

判断当前楼层时,最好用区间表示,如果判断它具体到了哪个值,有可能会捕捉不到。遍历每一个楼层看是否有符合条件的。

第一层要自己设置nav[0].style.color="",不然打开页面,网页不滚动也是监听不到第一层的位置情况。

在同一楼层内滚动代码会执行多次,修改后的代码:

楼层滚动
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body{
            background-color: black;
        }
        #content div{
            opacity: .5;
            height: 800px;
            background-color: red;
            font-size: 100px;
            line-height: 800px;
            text-align: center;
        }
        #nav{
            position:fixed;
            left: 50px;
            top: 200px;
            width: 50px;
            text-align: center;
        }
        #nav li{
            background-color: purple;
            height: 30px;
            line-height: 30px;
            color: white;
            list-style: none;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div id="content">
        <div>1</div>
        <div style="background:blue">2</div>
        <div style="background:orange">3</div>
        <div style="background:pink">4</div>
    </div>
    <ul id="nav">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
</body>
<script>
    var contents=content.children;
    var navs=nav.children;
    var x=0;
    var H=window.innerHeight||document.documentElement.clientHeight;
    H/=2;
    navs[x].style.background="green";
    for(var i=0;i<navs.length;i++){
        navs[i].index=i;
        navs[i].onclick=function(){
            var cur_st=document.body.scrollTop||document.documentElement.scrollTop;
            increase(cur_st,contents[this.index].offsetTop,200,function(s){
                // 直接获取offsettop是有可能不准的,用之前封装的那个方法就行
                console.log("s",s)
                document.body.scrollTop=s;
                document.documentElement.scrollTop=s;
            })
            // 这样你改变offsettop时,就会触发window的onscroll事件
            // 楼层导航按钮也会跟着变化
        }
    }
    function scrollHandle(){
        var st=document.body.scrollTop||document.documentElement.scrollTop;
        for(var i=0;i<contents.length;i++){
            var ot=contents[i].offsetTop;
            // 这里的800是元素的高度,这个应该要获取,不能直接写死
            if(ot<=st+H&&ot+800>st+H&&x!=i){
                //ot<st+H当前楼层的顶部向上越过了屏幕的中线
                //ot+800>st+H当前楼层的底部向下越过了屏幕的中线
                navs[x].style.background="purple";
                x=i;
                navs[x].style.background="green";
                console.log(x);
            }
        }
    }
    scrollHandle();
    //是为了解决滚动后刷新获取不到当前楼层的问题
    window.onscroll=scrollHandle;

    function increase(start,end,t,fun){
        var x=end-start;
        var step;
        step=x/t*16.7
        var timer=setInterval(function(){
            start+=step;
            if(Math.abs(start-end)<=Math.abs(step)){
                // 差值小于step就清除计时器
                start=end;
                clearInterval(timer)
            }
            fun(start);
        },16.7)
    }
</script>
</html>

这里用的是window.onscroll是一级dom事件,一级dom事件会有别覆盖的风险,一个页面有多个window.onscroll事件时就麻烦了(window是公共的,谁都可以给他绑定事件),所以以后开发项目尽量用事件监听。

事件监听封装

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button id="box">按钮</button>
</body>
<script>
    function addEvent(el,type,fn){
        if(el.addEventListener){
            el.addEventListener(type,fn)
            // 这里面也是有事件对象的
        }else{
            // 在IE当中this不是指向el,所以用call
            el.attachEvent("on"+type,function(e){
                // 这个e是事件对象
                fn.call(this,e)
                // 将事件对象传到fn内面
            })
        }
    }
    addEvent(box,"click",function(e){
        e=e||window.event;
        console.log(e.target||e.srcElement);
    })
</script>
</html>

可以将这些处理兼容或是像之前的ani、添加删除类名的这些封装好的函数都放在一个js文件中,到时候项目中需要就直接应用,就不用再处理这些底层的东西了。

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

推荐阅读更多精彩内容