jsvascript学习(十三)- scroll相关综合案例

案例素材可到这里领取, __提取码:ephx __

1. 商品展示案例

通过导航条滑动可不断看到后面的商品列表

  • 主要难点在于导航条长度与导航条左边距离的理算,类似于之前的等比缩放,详情可参考注释里面的笔记推算
  • 这里涉及几个鼠标事件,onmousedown、onmousemove以及onmouseup,方法中的return false格外需要注意, 如果没有的话在导航条移动过程中就会在两个鼠标事件中产生冲突
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{
            margin: 0;
            padding: 0;
            list-style: none;
            border:none;
        }

        #box{
            width: 800px;
            height: 200px;
            border: 1px solid #ddd;

            position: relative;
            margin: 100px auto;

            overflow: hidden;
        }

        #box ul{
            width: 2600px;
            position: absolute;
            left: 0;
            top: 20px;
        }

        #box ul li{
            float: left;
        }

        #box_bottom{
            position: absolute;
            left: 0;
            bottom: 0;
            background-color: #e8e8e8;

            width: 100%;
            height: 25px;
        }

        .mask{
            position: absolute;
            left: 0;
            top:0;
            height: 25px;
            background-color: orangered;
            border-radius: 12px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div id="box">
        <ul id="box_top">
            <li><img src="images/img1.jpg" alt=""></li>
            <li><img src="images/img2.jpg" alt=""></li>
            <li><img src="images/img3.jpg" alt=""></li>
            <li><img src="images/img4.jpg" alt=""></li>
            <li><img src="images/img5.jpg" alt=""></li>
            <li><img src="images/img6.jpg" alt=""></li>
            <li><img src="images/img7.jpg" alt=""></li>
            <li><img src="images/img8.jpg" alt=""></li>
            <li><img src="images/img1.jpg" alt=""></li>
            <li><img src="images/img2.jpg" alt=""></li>
            <li><img src="images/img1.jpg" alt=""></li>
            <li><img src="images/img2.jpg" alt=""></li>
            <li><img src="images/img3.jpg" alt=""></li>
            <li><img src="images/img4.jpg" alt=""></li>
            <li><img src="images/img5.jpg" alt=""></li>
            <li><img src="images/img6.jpg" alt=""></li>
            <li><img src="images/img7.jpg" alt=""></li>
            <li><img src="images/img8.jpg" alt=""></li>
            <li><img src="images/img1.jpg" alt=""></li>
            <li><img src="images/img2.jpg" alt=""></li>
        </ul>
        <div id="box_bottom">
            <span class="mask"></span>
        </div>
    </div>

<script>
    window.onload = function () {
        // 1. 获取需要的标签
        var box = document.getElementById("box");
        var box_top = document.getElementById("box_top");
        var box_bottom = document.getElementById("box_bottom");
        var mask = box_bottom.children[0];

        // 2. 设置滚动条的长度
        // 滚动条长度 = ( 盒子的宽度 / 内容的宽度) * 盒子的宽度
        var mask_len = (box.offsetWidth / box_top.offsetWidth) * box.offsetWidth;
        mask.style.width = mask_len + 'px';

        // 3. 鼠标操作
        mask.onmousedown = function (event) {
            var e = event || window.event;

            // 3.1 求出初始值
            var beginX = e.clientX - mask.offsetLeft;

            // 3.2 移动
            document.onmousemove = function (event) {
                var e = event || window.event;

                // 3.3 求出移动的距离
                var endX = event.clientX - beginX;

                // 边界值
                if(endX < 0){
                    endX = 0;
                }else if(endX >= box.offsetWidth - mask.offsetWidth){
                    endX = box.offsetWidth - mask.offsetWidth;
                }


                // 3.4 动起来
                mask.style.left = endX + 'px';

                // 内容走的距离 = (内容的长度 - 盒子的长度) \/ (盒子长度 - 滚动条的长度) * 滚动条走的距离
                var content_len = (box_top.offsetWidth - box.offsetWidth) / (box.offsetWidth - mask.offsetWidth) * endX;
                box_top.style.left = -content_len + 'px';

                return false;
            };

            document.onmouseup = function () {
                document.onmousemove = null;
            }
        }
    }
</script>
</body>
</html>

2. 瀑布流图片布局案例

按照瀑布流对图片进行布局展示,往下移动会自动生成图片持续展示

  • 难点在于对于图片大小以及屏幕宽度的把握
  • 对于每一排的图片,要计算出高度最低的盒子将下一排第一个盒子插入此处,并对最低高度进行更新,其他的按照这种模式循环处理

index.html:

  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>瀑布流布局</title>
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
    <div id="main">
        <div class="box"><div class="pic"><img src="images/img01.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img02.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img03.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img04.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img05.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img06.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img07.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img08.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img09.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img10.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img11.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img12.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img13.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img14.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img15.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img16.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img17.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img18.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img19.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img20.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img21.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img22.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img23.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img24.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img25.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img26.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img27.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img28.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img29.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img30.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img31.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img32.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img33.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img34.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img35.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img36.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img37.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img38.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img39.jpg" alt=""></div></div>
        <div class="box"><div class="pic"><img src="images/img40.jpg" alt=""></div></div>
    </div>
<script src="js/Underscore-min.js"></script>
<script src="js/myFunc.js"></script>
<script src="js/index.js"></script>
</body>
</html>

index.js:

window.onload = function () {
    // 1. 实现瀑布流布局
    waterFull("main", "box");

    // 2. 动态加载图片
    window.onscroll = function () {
        if(checkWillLoadImage()){
            // 2.1 造数据
            var dataArr = [
                {"src": "img04.jpg"},
                {"src": "img06.jpg"},
                {"src": "img08.jpg"},
                {"src": "img09.jpg"},
                {"src": "img10.jpg"},
                {"src": "img12.jpg"},
                {"src": "img14.jpg"},
                {"src": "img16.jpg"},
                {"src": "img18.jpg"}
            ];

            // 2.2 创建元素
            for(var i=0; i<dataArr.length; i++){
                var newBox = document.createElement("div");
                newBox.className = "box";
                $("main").appendChild(newBox);

                var newPic = document.createElement("div");
                newPic.className = "pic";
                newBox.appendChild(newPic);

                var newImg = document.createElement("img");
                newImg.src = "images/" + dataArr[i].src;
                newPic.appendChild(newImg);
            }

            // 2.3 重新布局
            waterFull("main", "box");
        }
    }
};

/**
 * 实现瀑布流布局
 */
function waterFull(parent, child) {
    // 1. 父盒子居中
    var allBox = $(parent).getElementsByClassName(child);// 1.1 获取所有的盒子

    // 1.2 获取子盒子的宽度
    var boxWidth = allBox[0].offsetWidth;
    // 1.3 获取屏幕的宽度
    var screenW = document.documentElement.clientWidth;
    // 1.4 求出列数
    var cols = parseInt(screenW / boxWidth);
    // 1.5 父盒子居中
    $(parent).style.width = cols * boxWidth + 'px';
    $(parent).style.margin = "0 auto";


    // 2. 子盒子的定位
    // 2.1 定义高度数组
    var heightArr = [], boxHeight = 0, minBoxHeight = 0, minBoxIndex = 0;
    // 2.2 遍历子盒子
    for (var i = 0; i < allBox.length; i++) {
        // 2.2.1 求出每一个子盒子的高度
        boxHeight = allBox[i].offsetHeight;
        // 2.2.2 取出第一行盒子的高度放入高度数组
        if (i < cols) { // 第一行
            heightArr.push(boxHeight);
        } else { // 剩余行
            // 1. 取出最矮的盒子高度
            minBoxHeight = _.min(heightArr);
            // 2. 求出最矮盒子对应的索引
            minBoxIndex = getMinBoxIndex(heightArr, minBoxHeight);
            // 3. 子盒子定位
            allBox[i].style.position = "absolute";
            allBox[i].style.left = minBoxIndex * boxWidth + 'px';
            allBox[i].style.top = minBoxHeight + 'px';
            // 4. 更新数组中的高度
            heightArr[minBoxIndex] += boxHeight;
        }
    }

    console.log(heightArr, minBoxHeight, minBoxIndex);
}
/**
 * 获取数组中最矮盒子高度的索引
 * @param arr
 * @param val
 * @returns {number}
 */
function getMinBoxIndex(arr, val) {
    for(var i=0; i<arr.length; i++){
        if(arr[i] === val){
            return i;
        }
    }
}
function $(id) {
    return typeof id === "string" ? document.getElementById(id) : null;
}
/**
 * 判断是否具备加载图片的条件
 */
function checkWillLoadImage() {
    // 1. 获取最后一个盒子
    var allBox = document.getElementsByClassName("box");
    var lastBox = allBox[allBox.length - 1];

    // 2. 求出最后一个盒子自身高度的一半 + offsetTop
    var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop;

    // 3. 求出屏幕的高度
    var screenW = document.body.clientHeight || document.documentElement.clientHeight;

    // 4. 求出页面偏离浏览器的高度
    var scrollTop = scroll().top;

    return lastBoxDis <= screenW + scrollTop;
}

myFunc.js里面是对scroll方法的封装,详情可参考上一节:

/**
 * 获取滚动的头部距离和左边距离
 * scroll().top scroll().left
 * @returns {*}
 */
function scroll() {
    if(window.pageYOffset !== null){
        return {
            top: window.pageYOffset,
            left: window.pageXOffset
        }
    }else if(document.compatMode === "CSS1Compat"){ // W3C
        return {
            top: document.documentElement.scrollTop,
            left: document.documentElement.scrollLeft
        }
    }

    return {
        top: document.body.scrollTop,
        left: document.body.scrollLeft
    }
}

参考:
网易云js课程

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

推荐阅读更多精彩内容