1. 程式人生 > >jQuery實戰6:優雅的彈窗效果

jQuery實戰6:優雅的彈窗效果

彈窗是網頁中經常看到的效果,以前的彈窗是用window.open()等方式在瀏覽器視窗新建另一個新視窗來完成的,這種彈窗方式現在已經被很多瀏覽器所攔截。今天我們來用更加友好的方式來實現彈窗效果。完成的功能效果如圖:

這裡寫圖片描述

如圖,在瀏覽器的左上方是兩個button按鈕,按下之後分別彈出左下角的視窗和中間的視窗,右下角的視窗當頁面載入完成之後自動慢慢顯示,之後又徐徐的淡出。基於div+css的模式,我們的先來建立html頁面。

window.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>jQuery實戰:視窗效果</title> <link type="text/css" rel="stylesheet" href="../css/window.css" /> <script type="text/javascript" src="../js/jquery-1.7.2.min.js"></script> <script
type="text/javascript" src="../js/window.js">
</script> </head> <body> <input type="button" value="左下角顯示視窗" id="leftpop" /> <input type="button" value="螢幕中間顯示視窗" id="centerpop" /> <div class="window" id="left"> <div class="title"> <img
alt="關閉" src="../image/close.gif" />
我是左邊顯示視窗的標題欄 </div> <div class="content"> 我是左邊顯示視窗的內容區 </div> </div> <div class="window" id="center"> <div class="title"> <img alt="關閉" src="../image/close.gif" /> 我是中間顯示視窗的標題欄 </div> <div class="content"> <p>我是中間顯示視窗的內容區</p> </div> </div> <div class="window" id="right"> <div class="title"> <img alt="關閉" src="../image/close.gif" /> 我是右邊顯示視窗的標題欄 </div> <div class="content"> 我是右邊顯示視窗的內容區 </div> </div> </body> </html>

從html程式碼中可以看到,這裡的視窗是用div來實現的,目前的html程式碼只是描繪了頁面的基本骨架,能夠效果離視窗效果還相差甚遠,不過別急,新增上css程式碼,頁面相對就好看多了。

window.css

.window {
    background-color: #D0DEF0;
    width: 250px;
    /*padding: 2px;*/
    margin: 5px;
    /*控制視窗絕對定位*/
    position: absolute;
    display: none;
}
.content {
    height: 150px;
    background-color: white;
    border: 2px solid #D0DEF0;
    padding: 2px;
    /*控制區域內容超過指定高度和寬度時顯示滾動條*/
    overflow: auto;
}
.title {
    padding: 4px;
    font-size: 14px;
}
.title img {
    width: 14px;
    height: 14px;
    float: right;
    cursor: pointer;
}

為了看到當前效果,先將.window的display屬性註釋掉,或者將它的屬性值改為”block”,看到的效果如圖:
這裡寫圖片描述

其實三個視窗是由三個div組成,每個div分為title和content兩部分,title是標題欄區域,content是內容區域。為了達到視窗的視覺效果,給我們的title標題欄區域加背景顏色background-color,然後給我們的content內容區域加邊框border: 2px solid #D0DEF0;,邊框的顏色與標題欄一致。此時的效果如上圖,目前只能看到一個視窗的原因是三個div佔據了相同的位置,第三個視窗遮蓋住了前兩個視窗。不過沒關係,我們可以用JavaScript程式碼來控制三個div的位置。

jQuery庫函式提供了豐富多彩的外掛功能,今天我們來編寫自己的外掛,簡單的案例如下:

$.fn.hello = function() {
    alert("hello:" + this.val());
    return this;
}

只需要在需要的地方註冊上本外掛就行了。相應的,這裡我們編寫的外掛mywin來專門處理我們的視窗功能效果。
window.js

/**
* 視窗位置的外掛
*/
$.fn.mywin = function() {
    var windowobj = $(window);
    var browserWidth = $(window).width();
    var browserHeight = $(window).height();
    var scrollLeft = $(window).scrollLeft();
    var scrollTop = $(window).scrollTop();
    var cwinwidth = this.width();
    var cwinheight = this.height();
    var left = scrollLeft + (browserWidth - cwinwidth)/2;
    var top = cwinheight + (browserHeight - cwinheight)/2;
    this.css("left", left).css("top", top);
    $(this.children(".title").children("img")).click(function() {
        $(this).parent().parent().hide("slow");
    });

    return this;
}

上訴程式碼編寫了本應用中中間視窗案例的外掛,呼叫程式碼如下:

window.js

$(document).ready(function() {
    $("#centerpop").click(function() {
        $("#center").mywin().show("slow");
    });
});

外掛中的程式碼思路是:為了計算視窗div的left和top屬性值,我們需要拿到瀏覽器視窗的長browserWidth和寬browserHeight,以及視窗是否因為內容過多而又滾動條的位置scrollLeft和scrollTop。視窗div的left值=滾動條橫座標+(瀏覽器視窗的橫向長度-視窗div橫向長度)/2,top值=滾動條縱座標+(瀏覽器視窗的縱向長度-視窗div縱向長度)/2。

最終完成完整的jQuery程式碼如下:

$(document).ready(function(){
    var centerwin = $("#center");
    var leftwin = $("#left");
    var rightwin = $("#right");
    $("#centerpop").click(function(){
        //滑鼠點選按鈕之後,把id為center的視窗顯示在頁面中間
        //計算位於螢幕中間的視窗的左邊界和上邊界的值
        //瀏覽器可視區域的寬和高,當前視窗的寬和高
        //需要考慮到橫向滾動條的當前左邊界值以及縱向滾動條的當前上邊界值
        centerwin.show("slow");
    });
    $("#leftpop").click(function() {
        leftwin.slideDown("slow");
    });

    setTimeout(function () {
        centerwin.mywin({left: "center", top: "center"});
        leftwin.mywin({left: "left", top: "bottom"}, function(){
            leftwin.slideUp("slow");
        });
        var windowobj = $(window);
        var cwinwidth = rightwin.outerWidth(true);
        var cwinheight = rightwin.outerHeight(true);
        var browserwidth = windowobj.width();
        var browserheight = windowobj.height();
        var scrollLeft = windowobj.scrollLeft();
        var scrollTop = windowobj.scrollTop();
        var rleft = scrollLeft + browserwidth - cwinwidth;
        if ($.browser.safari) {
            rleft = rleft - 15;
        }
        if ($.browser.opera) {
            rleft = rleft + 15;
        }
        if ($.browser.msie && $.browser.version.indexOf("8") >= 0) {
            rleft = rleft - 20;
        }
        rightwin.mywin({left: "right", top: "bottom"}, function() {
            rightwin.hide();
        },{left: rleft, top: scrollTop + browserheight}).fadeOut(15000).dequeue();
    },500);

});

/**
 *@param position表示視窗的最終位置,包含兩個屬性,一個是left,一個是top
 *@param hidefunc表示執行視窗隱藏的方法
 *@param initPos表示視窗初始位置,包含兩個屬性,一個是left,一個是top
 */
$.fn.mywin = function(position, hidefunc, initPos) {
    if (position && position instanceof Object) {
        var positionleft = position.left;
        var positiontop = position.top;

        var left;
        var top;
        var windowobj = $(window);
        var currentwin = this;
        var cwinwidth;
        var cwinheight;

        var browserwidth;
        var browserheight;
        var scrollLeft;
        var scrollTop;
        //計算瀏覽器當前可視區域的寬和高,以及滾動條左邊界,上邊界的值
        function getBrowserDim() {
            browserwidth = windowobj.width();
            browserheight = windowobj.height();
            scrollLeft = windowobj.scrollLeft();
            scrollTop = windowobj.scrollTop();  
        }       
        //計算視窗真實的左邊界值
        function calLeft(positionleft, scrollLeft, browserwidth, cwinwidth) {
            if (positionleft && typeof positionleft == "string") {
                if (positionleft == "center") {
                    left = scrollLeft + (browserwidth - cwinwidth) / 2; 
                } else if (positionleft == "left") {
                    left = scrollLeft;  
                } else if (positionleft == "right") {
                    left = scrollLeft + browserwidth - cwinwidth;
                    if ($.browser.safari) {
                        left = left - 15;
                    }
                    if ($.browser.opera) {
                        left = left + 15;
                    }
                    if ($.browser.msie && $.browser.version.indexOf("8") >= 0) {
                        left = left - 20;
                    }
                } else  {
                    left = scrollLeft + (browserwidth - cwinwidth) / 2; 
                }
            } else if (positionleft && typeof positionleft == "number") {
                left = positionleft;
            } else {
                left = 0;
            }
        }
        //計算視窗真實的上邊界值       
        function calTop(positiontop, scrollTop, browserheight, cwinheight) {
            if (positiontop && typeof positiontop == "string") {
                if (positiontop == "center") {
                    top = scrollTop + (browserheight - cwinheight) / 2;
                } else if (positiontop == "top") {
                    top = scrollTop;
                } else if (positiontop == "bottom") {
                    top = scrollTop + browserheight - cwinheight;
                    if ($.browser.opera) {
                        top = top - 25;
                    }
                } else {
                    top = scrollTop + (browserheight - cwinheight) / 2;
                }
            } else if (positiontop && typeof positiontop == "number") {
                top = positiontop;
            } else {
                top = 0;
            }
        }
        //移動視窗的位置
        function moveWin() {
            calLeft(currentwin.data("positionleft"), scrollLeft, browserwidth, cwinwidth);
            calTop(currentwin.data("positiontop"), scrollTop, browserheight, cwinheight);
            currentwin.animate({
                left: left,
                top: top
            },600); 
        }

        //定義關閉按鈕的動作
        currentwin.children(".title").children("img").click(function() {
            if (!hidefunc) {
                currentwin.hide("slow") ;
            } else {
                hidefunc();
            }
        });

        if (initPos && initPos instanceof Object) {
            var initLeft = initPos.left;
            var initTop = initPos.top;
            if (initLeft && typeof initLeft == "number") {
                currentwin.css("left", initLeft);   
            } else {
                currentwin.css("left", 0);
            }
            if (initTop && typeof initTop == "number") {
                currentwin.css("top", initTop); 
            } else {
                currentwin.css("top", 0);
            }
            currentwin.show();
        }
        cwinwidth = currentwin.outerWidth(true);
        cwinheight = currentwin.outerHeight(true);
        currentwin.data("positionleft", positionleft);
        currentwin.data("positiontop", positiontop);
        getBrowserDim();
        moveWin();

        var scrollTimeout;
        //瀏覽器滾動條滾動時,移動視窗的位置
        $(window).scroll(function(){
            //判斷一下當前視窗是否可見
            if (!currentwin.is(":visible")) {
                return; 
            }
            clearTimeout(scrollTimeout);
            scrollTimeout = setTimeout(function(){
                getBrowserDim();        
                moveWin();
            },300);
        });
        //瀏覽器大小改變時,移動視窗的位置
        $(window).resize(function(){
            //判斷一下當前視窗是否可見
            if (!currentwin.is(":visible")) {
                return; 
            }
            getBrowserDim();    
            moveWin();  
        });
        //返回當前物件,以便可以級聯的執行其他方法
        return currentwin;
    }
}

左下角和中間視窗的div是靠觸發click事件來顯示視窗,在滾動條滾動時觸發scroll事件來重新呼叫計算div的top和left的函式。右下角的視窗是徐徐升起的視窗,所以在文件載入完成的時候就顯示視窗,處理的程式碼是放在setTimeout()事件裡面,setTimeout函式裡面的fadeOut讓視窗達到漸變透明的效果。

案例程式碼託管地址:https://github.com/shizongger/JqueryInAction