從零開始學 Web 之 移動Web(四)實現JD分類頁面

你們好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......javascript

在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的項目。如今就讓咱們一塊兒進入 Web 前端學習的探索之旅吧!css

實現JD分類頁面

咱們先看看要實現的效果圖:html

一、項目需求:

  • 全屏頁面
  • 右側的頁面隨着頁面寬度的變化而變化,左側欄寬度固定不變。
  • 左側欄能夠上下滑動,若是滑動超出上下範圍自動反彈回去
  • 點擊左側欄每一個項目,自動滾動左側欄使得項目置頂
  • 當點擊項目可能使得超出滑動範圍的時候,以滑動範圍爲準,當前點擊的項目沒必要置頂。

二、項目分析

如何實現一個全屏頁面,沒有滾動條?前端

以下面的結構:大盒子1和大盒子2分爲上下結構,小盒子3和小盒子4在大盒子2的內部,分爲左右結構。java

那麼如何排布,使得上下左右都沒有滾動條呢?git

思路:github

一、要使得大盒子1和大盒子2上下沒有滾動條,可使得大盒子1 的寬度爲 100%,高度加入100px,大盒子2的高度 100%;這時會超出100px的高度,若是這時咱們讓大盒子1定位(position:absolute;),,確實能夠實現上下沒有滾動條,可是大盒子的頭部100px 的位置會被覆蓋,因此再讓大盒子2 padding-top: 100px; 就能夠了。微信

二、要使得小盒子3和小盒子4左右沒有滾動條,可不能夠參考大盒子1和大盒子2的策略呢?讓小盒子3 寬度100px,高度100%,小盒子4寬度100%,高度100%,而後小盒子3定位(position:absolute;),這是不能夠的,由於小盒子3的高度是100%,參照父盒子(大盒子2)的,因此高度是整個視口的高度,而大盒子1佔了位置,因此小盒子3只能往下挪,在底部衝出100px的大小,沒法彌補。dom

那麼怎麼辦呢?ide

第一,能夠將小盒子3定位(position:absolute;)改成浮動(float:left);

第二,能夠取消大盒子2的寬度100%,改成 margin-left:100px;小盒子3依然浮動(float:left),也是能夠的。

三、示例代碼:

相關源碼以放置 Github:https://github.com/Daotin/Web/tree/master/Code/src/11/jd.zip

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="./css/base.css">
    <link rel="stylesheet" href="./css/category.css">
    <script src="./js/category.js"></script>
    <script src="./js/tap.js"></script>
    <title>Document</title>
</head>
<body>
    <div class="layout">
        <!-- 頭部header -->
        <div class="header">
            <div class="header-back"></div>
            <form action="" class="header-text">
                <input type="text" placeholder="請輸入商品名稱">
            </form>
            <div class="header-menu"></div>
        </div>
        <!-- 主體main -->
        <div class="main">
            <div class="main-left">
                <span>拉這麼多想幹嗎?</span>
                <ul>
                    <li class=""><a href="javascript:;">熱門推薦</a></li>
                    <li class="active"><a href="javascript:;">潮流女裝</a></li>
                    <li class=""><a href="javascript:;">品牌男裝</a></li>
                    <li class=""><a href="javascript:;">內衣配飾</a></li>
                    <li class=""><a href="javascript:;">家用電器</a></li>
                    <li class=""><a href="javascript:;">電腦辦公</a></li>
                    <li class=""><a href="javascript:;">手機數碼</a></li>
                    <li class=""><a href="javascript:;">母嬰頻道</a></li>
                    <li class=""><a href="javascript:;">圖書</a></li>
                    <li class=""><a href="javascript:;">家居家紡</a></li>
                    <li class=""><a href="javascript:;">居家生活</a></li>
                    <li class=""><a href="javascript:;">傢俱建材</a></li>
                    <li class=""><a href="javascript:;">熱門推薦</a></li>
                    <li class=""><a href="javascript:;">潮流女裝</a></li>
                    <li class=""><a href="javascript:;">品牌男裝</a></li>
                    <li class=""><a href="javascript:;">內衣配飾</a></li>
                    <li class=""><a href="javascript:;">家用電器</a></li>
                    <li class=""><a href="javascript:;">電腦辦公</a></li>
                    <li class=""><a href="javascript:;">手機數碼</a></li>
                    <li class=""><a href="javascript:;">母嬰頻道</a></li>
                    <li class=""><a href="javascript:;">圖書</a></li>
                    <li class=""><a href="javascript:;">家居家紡</a></li>
                    <li class=""><a href="javascript:;">居家生活</a></li>
                    <li class=""><a href="javascript:;">傢俱建材</a></li>
                </ul>
            </div>
            <div class="main-right">
                <a href="javascript:;" class="main-right-img">
                    <img src="./uploads/banner_1.jpg" alt="">
                </a>
                <h3>商品分類</h3>
                <div class="main-right-cate">
                    <ul>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                        <li>
                            <a href="javascript:;">
                                <img src="./uploads/nv-fy.jpg" alt="">
                                <p>毛衣</p>
                            </a>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

CSS 代碼:

html, body {
    width: 100%;
    height: 100%;
}

.layout {
    width: 100%;
    height: 100%;
}

/* 頭部header */
.header {
    width: 100%;
    height: 50px;
    background-color: #eee;
    border-bottom: 1px solid #ccc;
    position: absolute;
}
.header-back,
.header-menu {
    width: 50px;
    height: 50px;
    background: url("../images/jd-sprites.png");
    background-size: 200px 200px;
    position: absolute;
    top: 0;
    padding: 15px;
    background-origin: content-box;
    background-clip: content-box;
}
.header-back {
    background-position: -20px 0;
    left: 0;
}
.header-menu {
    background-position: -60px 0;
    right: 0;
}
.header-text {
    padding: 0 60px;
}
.header-text > input {
    width: 100%;
    height: 30px;
    margin-top: 10px;
    border-radius: 10px;
    padding-left: 10px;
    font-size: 16px;
    color: #aaa;
}


/* 主體main */
.main {
    width: 100%;
    height: 100%;
    padding-top: 50px;
}
.main-left {
    width: 100px;
    height: 100%;
    float: left;
    overflow: hidden;
    position: relative;
    background: #eee;
}
.main-left > span {
    display: inline-block;
    width: 100%;
    font-size: 10px;
    color: #ccc;
    text-align: center;
    margin-top: 80px;
}
.main-left ul {
    width: 100px;
    position: absolute;
    left: 0;
    top: 0;
}
.main-left ul li {
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    border-right: 1px solid #ccc;
    border-bottom: 1px solid #ccc;
    background-color: #eee;
}
.main-left li.active {
    background-color: #fff;
    border-bottom: 1px solid #ccc;
    border-right: 1px solid #ccc;
}
.main-left li.active a {
    color: #e92322;
}
.main-left a {
    display: block;
    width: 100%;
    height: 50px;
    color: #666;
}
.main-right {
    /* width: 100%; */
    height: 100%;
    margin-left: 100px;
    /* 設置爲伸縮盒子 */
    display: flex;
    flex-direction: column;
}
.main-right-img {
    width: 100%;
}
.main-right-img > img {
    width: 100%;
    /* 消除基線 */
    display: block;
}
.main-right > h3 {
    font-size: 14px;
    font-weight: bold;
    color: #333;
    margin: 10px 0 10px 5px;
}
.main-right-cate {
    width: 100%;
    /* 下面兩個一塊兒使得沒有上下滾動條 */
    flex: 1;
    overflow: hidden;
}

.main-right-cate> ul {
    width: 100%;
}
.main-right-cate > ul > li {
    width: 33.33%;
    text-align: center;
    float: left;
}

原生 js 代碼:

window.onload = function () {  
    leftSlideEffect();
};

// 左側滑動欄效果和點擊效果
function leftSlideEffect() {  
    // 添加左側欄的滑動效果
    var mainObj = document.querySelector(".main");
    var leftUlObj = document.querySelector(".main-left").children[1];

    var mainLeftHeight = document.querySelector(".main-left").offsetHeight;
    var leftUlObjHeight = leftUlObj.offsetHeight;

    var liObjs = leftUlObj.querySelectorAll("li");


    var startY=0; // 起始位置
    var diffY=0;  // 滑動後與起始位置的偏移
    var currentY=0; // 保存每次滑動後的偏移

    var maxTop = 0; // 最大top偏移值
    var minTop = mainLeftHeight-leftUlObjHeight; // 最大top偏移值
    var maxBounceTop = maxTop + 100; //彈性最大高度
    var minBounceTop = minTop - 100; //彈性最小高度
    leftUlObj.addEventListener("touchstart", function(e) {
        // 計算起始座標
        startY = e.targetTouches[0].clientY;
    });

    leftUlObj.addEventListener("touchmove", function(e) {
        /*計算距離的差別*/
        diffY = e.targetTouches[0].clientY - startY;
        /*判斷滑動的時候是否超出當前指定的滑動區間*/
        if((diffY+currentY > maxBounceTop) || (diffY+currentY < minBounceTop)) {
            return;
        }
        /*先將以前可能添加的過渡效果清除*/
        leftUlObj.style.transition = "none";
        /*實現偏移操做:應該在以前的滑動距離的基礎之上再進行滑動*/
        leftUlObj.style.top = diffY+currentY + "px";
    });

    leftUlObj.addEventListener("touchend", function() {
        
        if(diffY+currentY > maxTop) {
            // 回到maxTop位置,設置currentY當前值
            leftUlObj.style.transition = "top 0.5s"
            leftUlObj.style.top = maxTop + "px";
            currentY = maxTop;
        } else if(diffY+currentY < minTop) {
            // 回到minTop位置,設置currentY當前值
            leftUlObj.style.transition = "top 0.5s"
            leftUlObj.style.top = minTop + "px";
            currentY = minTop;
        } else {
            // 記錄當前滑動的距離
            currentY += diffY;
        }
    });

   // -----------------------------------------------------
  
    // 左側滑動欄點擊效果
    /*爲每個li元素設置添加一個索引值*/
    for(var i=0; i<liObjs.length; i++) {
        // liObjs是對象,給對象增長屬性值
        liObjs[i].index = i;
    }
    // 點擊事件
    fingerTap.tap(leftUlObj, function (e) {
        // 清除全部li標籤
        for(var i=0; i<liObjs.length; i++) {
            liObjs[i].classList.remove("active");
        }
        //設置點擊的li標籤的樣式
        var indexLi = e.target.parentElement;
        
        indexLi.classList.add("active");
        // 每一個li標籤的高度
        var indexLiHeight = indexLi.offsetHeight;

        /*2.移動當前的li元素到父容器的最頂部,可是不能超出以前設定了靜止狀態下的最小top值*/
        leftUlObj.style.transition = "top 0.5s";

        if(-indexLiHeight*indexLi.index < minTop) {
            leftUlObj.style.top = minTop + "px";
            // 記得重置currentY的值
            currentY=minTop;
        } else {
            leftUlObj.style.top = -indexLiHeight*indexLi.index + "px";
            // 記得重置currentY的值
            currentY=-indexLiHeight*indexLi.index;
        }
    });
}

把點擊事件封裝成一個單獨 js 庫,tap.js。

// 封裝移動端的tap事件

var fingerTap = {
    tap: function (dom, callback) {  
        // 判斷dom是否存在
        if((!dom) || (typeof dom != "object")) {
            return;
        }
        var startX, startY, endX, endY, startTime, endTime;
        dom.addEventListener("touchstart", function (e) {  
            // 不止一個手指
            if(e.targetTouches.length > 1) {
                return;
            }
            startX = e.targetTouches[0].clientX;
            startY = e.targetTouches[0].clientY;
            
            // 點擊時記錄毫秒數
            startTime = Date.now(); 

        });

        dom.addEventListener("touchend", function (e) {
            // 不止一個手指
            if(e.changedTouches.length > 1) {
                return;
            }
            // 之因此使用changedTouches,是由於手指離開後就沒有targetTouches了
            endX = e.changedTouches[0].clientX;
            endY = e.changedTouches[0].clientY;
            // 記錄離開手指的毫秒數
            endTime = Date.now();
            //若是是長按操做就返回
            if(endTime - startTime > 300) {
                return;
            }
            // 判斷從按下到擡起手指在必定的範圍滑動也算tap事件
            if((Math.abs(endX-startX) <= 6) && (Math.abs(endY-startY) <= 6)) {
                // tap點擊事件的處理函數
                callback && callback(e);
            }
        });
    }
};

四、使用 Zepto 實現點擊操做

上面 tap.js 是咱們本身封裝的點擊事件,其實在 Zepto 中,已經封裝好了 tap 單擊事件,咱們能夠直接使用。

只須要將

fingerTap.tap(leftUlObj, function (e) {});

改成:

$(leftUlObj).on("tap", function() {});

就能夠實現相同的效果。

相關文章
相關標籤/搜索