可拖動彈窗的JS和jQuery兩種寫法


      最近在慕課網上學習了一個網頁可拖動對話框js實現的演示視頻,這個demo中的例子是百度首頁登錄按鈕的彈窗,如下圖:

1611211456_1_thumb1

       當點擊左上角的登錄按鈕時,彈窗出現並自動居中,同時窗口可拖動的范圍被限制在了可視區域內,即瀏覽器視窗的上下左右邊界,彈窗無法移出移動出四個邊界,也不會出現滾動條。

1611211459_2_thumb31611211504_3_thumb21611211505_4_thumb2

      另一個效果就是,當改變窗口大小時,對話框自動居中

      這個視頻中用了原生js,jQuery兩種寫法實現案例,但本質上,對話框居中,限制拖動范圍的的計算思路是一致的。

      為了簡化頁面,總結核心思路,我重新寫了一個小demo,界面如下:

1611211515_5_thumb2

1611211516_6_thumb2               1611211524_7_thumb3

      依舊保持着點擊彈出按鈕,對話框自動居中,拖動范圍限制,改變窗口大小彈窗居中等效果,下面是本demo的HTMl結構和CSS布局代碼:

HTML結構代碼

<div id="callout" class="button callout_button"><a href="#">彈出對話框</a></div>
<div id="mask" class="mask"></div>
<div class="dialog" id="dialog">
    <div class="dialog_head" id="move_part">可拖拽部分</div>
    <div class="dialog_content"></div>
    <div class="button close_button" id="close"><a href="#">點我關閉對話框</a>
    </div>
</div>

CSS樣式代碼

<style type="text/css">
    a{text-decoration: none; color: #eee; display: block;}
    .button{width: 200px; height: 50px; border-radius: 20px; text-align:center;line-height: 50px;}
    .callout_button{background:#FF5B5B;margin:0 auto; }
    .callout_button:hover{background: red;}
    .close_button{background:#363636;margin:0 auto;}
    .close_button:hover{background: black;}
    .mask{width: 100%;height: 100%;background:#000;position: absolute;top: 0px;left:0px;opacity: 0.4;z-index: 8000; display: none;-moz-user-select: none; -webkit-user-select: none;}
    .dialog{width: 380px;background:#fff; position: absolute;z-index: 9000;padding-bottom: 10px; display: none;-moz-user-select: none; -webkit-user-select: none;}
    .dialog_head{width: 100%;height:50px;background:#4B4B4B;text-align: center;line-height: 50px;color: #eee; cursor: move;}
    .dialog_content{width: 100%;height:300px;}
</style>

下面是重點的JS部分,先介紹

一、原生JS的寫法:

這里有一個比較實用的技巧,首先定義一個g()函數用於獲取對象

function g(id){return document.getElementById(id)};

這個函數用起來很方便,用於獲取對象,在原生JS種可以少寫很多代碼,有一點JS封裝的思想(感覺上,不知道說的對不對)。

彈出和關閉對話框

//點擊彈出對話框
        g('callout').onclick = function(){
            g('dialog').style.display = 'block';
             g('mask').style.display = 'block';
             autoCenter(g('dialog'));
        };
//點擊關閉對話框
        g('close').onclick = function(){
            g('dialog').style.display = 'none';
             g('mask').style.display = 'none';
        };

點擊拖動對話框有個重要的內容就是要設置對話框內容不可被選中

//禁止選中對話框內容
        if(document.attachEvent) {//ie的事件監聽,拖拽div時禁止選中內容,firefox與chrome已在css中設置過-moz-user-select: none; -webkit-user-select: none;
            g('dialog').attachEvent('onselectstart', function() {
              return false;
            });
        }

點擊彈出對話框中代碼中的autoCenter()函數,讓對話框保持自動居中

function autoCenter(el){
            //獲取可見窗口大小
            var bodyW = document.documentElement.clientWidth;
            var bodyH = document.documentElement.clientHeight;
            //獲取對話框寬、高
            var elW = el.offsetWidth;
            var elH = el.offsetHeight;

            el.style.left = (bodyW - elW)/2 + 'px';
            el.style.top = (bodyH - elH)/2 + 'px';
        };

當窗口改變大小時,對話框自動居中

//窗口大小改變時,對話框始終居中
        window.onresize = function(){
            autoCenter(g('dialog'));
        };

最核心的部分來了,對話框拖動的實現這個效果的實現要分為三個步驟:

1.鼠標點擊時,設置對話框可拖動,記錄鼠標的初始位置;

2.鼠標拖動時,根據鼠標新位置更新對話框位置(有兩種算法);

3.鼠標離開時移出對話框可拖動屬性;

第一步:鼠標按下時

//聲明需要用到的變量
        var mx = 0,my = 0;      //鼠標x、y軸坐標(相對於left,top)
        var dx = 0,dy = 0;      //對話框坐標(同上)
        var isDraging = false;      //不可拖動

        //鼠標按下
        g('move_part').addEventListener('mousedown',function(e){
            var e = e || window.event;
            mx = e.pageX;      //點擊時鼠標X坐標
              my = e.pageY;      //點擊時鼠標Y坐標
              dx = g('dialog').offsetLeft;
            dy = g('dialog').offsetTop;
            isDraging = true;      //標記對話框可拖動
        });

第二步:鼠標移動時

document.onmousemove = function(e){
            var e = e || window.event;
            var x = e.pageX;      //移動時鼠標X坐標
              var y = e.pageY;      //移動時鼠標Y坐標
              if(isDraging){        //判斷對話框能否拖動
                var moveX = dx + x - mx;      //移動后對話框新的left值
                var moveY = dy + y - my;      //移動后對話框新的top值
                g('dialog').style.left = moveX +'px';       //重新設置對話框的left
              g('dialog').style.top =  moveY +'px';     //重新設置對話框的top

            };
};

前面提過更新對話框位置有兩種算法,這里用的是第一種方法:

       先算出鼠標移動的坐標偏移量,用對話框的位置(對話框top,left值)加上這個偏移量就是對話框新的位置;

這種方法是參考了另一篇博客,原文地址http://www.jb51.net/article/67663.htm,慕課網的教學視頻中采用的是另一種算法:

       先算出鼠標按下時的坐標和對話框位置(對話框top,left值)的距離,再用鼠標移動的新坐標減去得到的距離更新對話框位置;即

     moveX = mx – (x – dx);

      moveY = my – (y – dy);

無論哪種辦法都可以實現對話框的拖動。

第三步:鼠標離開時

//鼠標離開
        g('move_part').addEventListener('mouseup',function(){
            isDraging = false;
        });

這一步比較簡單,重新設置對話框不可拖動。

另一個比較重要的是限制對話框的拖動范圍,代碼如下(這段代碼應插入到第二步的if判斷中

//設置拖動范圍
                  var pageW = document.documentElement.clientWidth;
                var pageH = document.documentElement.clientHeight;
                var dialogW = g('dialog').offsetWidth;
                var dialogH = g('dialog').offsetHeight;
                var maxX = pageW - dialogW;       //X軸可拖動最大值
                   var maxY = pageH - dialogH;       //Y軸可拖動最大值
                   moveX = Math.min(Math.max(0,moveX),maxX);     //X軸可拖動范圍
                   moveY = Math.min(Math.max(0,moveY),maxY);     //Y軸可拖動范圍

                  g('dialog').style.left = moveX +'px';       //重新設置對話框的left
                g('dialog').style.top =  moveY +'px';        //重新設置對話框的top

限制對話框在可視窗口內拖動,原理就是設置合理的對話框的left、top值范圍,其中

     left值的范圍是:【0,pageW – dialogW】

     top值的范圍是:【0,pageH – dialogH】

需要注意的是給這兩個值設定范圍的Math.max(),Math.min()方法。

下面是jQuery寫法的具體代碼,由於原理在JS部分中已有介紹,這里就不贅述了。

二、jQuery寫法

$(document).ready(function(){
            var $dialog = $("#dialog");
            var $mask = $("#mask");
            
            //自動居中對話框
            function autoCenter(el){
                var bodyW = $(window).width();
                var bodyH = $(window).height();
                var elW = el.width();
                var elH = el.height();
                $dialog.css({"left":(bodyW-elW)/2 + 'px',"top":(bodyH-elH)/2 + 'px'});        
            };
            
            //點擊彈出對話框
            $("#callout").click(function(){
                $dialog.css("display","block"); 
                $mask.css("display","block");
                autoCenter($dialog); 
            });            
            
            //禁止選中對話框內容
            if(document.attachEvent) {//ie的事件監聽,拖拽div時禁止選中內容,firefox與chrome已在css中設置過-moz-user-select: none; -webkit-user-select: none;
                g('dialog').attachEvent('onselectstart', function() {
                  return false;
                });
            }
            //聲明需要用到的變量
            var mx = 0,my = 0;      //鼠標x、y軸坐標(相對於left,top)
            var dx = 0,dy = 0;      //對話框坐標(同上)
            var isDraging = false;      //不可拖動

            //鼠標按下
            $("#move_part").mousedown(function(e){
                e = e || window.event;
                mx = e.pageX;     //點擊時鼠標X坐標
                my = e.pageY;     //點擊時鼠標Y坐標
                dx = $dialog.offset().left;
                dy = $dialog.offset().top;
                isDraging = true;      //標記對話框可拖動                
            });

            //鼠標移動更新窗口位置
            $(document).mousemove(function(e){
                var e = e || window.event;
                var x = e.pageX;      //移動時鼠標X坐標
                var y = e.pageY;      //移動時鼠標Y坐標
                if(isDraging){        //判斷對話框能否拖動
                    var moveX = dx + x - mx;      //移動后對話框新的left值
                    var moveY = dy + y - my;      //移動后對話框新的top值
                    //設置拖動范圍
                    var pageW = $(window).width();
                    var pageH = $(window).height();
                    var dialogW = $dialog.width();
                    var dialogH = $dialog.height();
                    var maxX = pageW - dialogW;       //X軸可拖動最大值
                    var maxY = pageH - dialogH;       //Y軸可拖動最大值
                    moveX = Math.min(Math.max(0,moveX),maxX);     //X軸可拖動范圍
                    moveY = Math.min(Math.max(0,moveY),maxY);     //Y軸可拖動范圍
                    //重新設置對話框的left、top
                    $dialog.css({"left":moveX + 'px',"top":moveY + 'px'});
                };
            });

            //鼠標離開
            $("#move_part").mouseup(function(){
                isDraging = false;
            });

            //點擊關閉對話框
            $("#close").click(function(){
                $dialog.css("display","none");
                $mask.css("display","none");
            });

            //窗口大小改變時,對話框始終居中
            window.onresize = function(){
                autoCenter($dialog);
            };
        });

注意分析對比原生JS和jQuery的異同點!獲取元素寬高,綁定事件等的寫法………….

三、末尾

可拖拽對話框效果實現,JS和jQuery兩種寫法就是這樣了,感謝前人栽陰!

同時學海無涯苦作舟,js插件不僅要會用,努力弄懂一個又一個效果的實現原理,自己能寫出來才是真的懂了,共勉!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM