IT技術互動交流平臺

在限制范圍內拖拽div吸附事件捕獲

作者:風沙渡  發布日期:2014-09-24 21:33:08

一、實現的效果是在限制范圍內拖拽div+吸附+事件捕獲。

這里需要理解的是事件捕獲,這個事件捕獲也是為了兼容div在拖拽過程中,文本不被選中這個問題。

如此良辰美景,拖拽也可以很灑脫哈。先看看圖,

二、一步步的實現這個拖拽過程的幾個要求

(一)拖拽起來

里面的邊框是表示頁面哦(我們的屏幕所能看到的東東)。

獲取移動距離的思路:

記錄鼠標按下和鼠標抬起兩次的坐標,然后相減,再加上div跟邊緣之間的間距。就得到移動距離。

之前我也在這里困惑了,不明白為什么還要再加上offsetLeft。原因就是clientX獲取到的是數值是不加上div跟邊緣的距離,不是marin,也不是padding,而是瀏覽器渲染的問題。

[下面是我自己的理解:

終于明白這個移動距離是如何計算出來的:

將式子化簡之后,得到的就是移動后的Div  clientX-移動前clientX,然后再加上offsetLeft,因為這個clientX是沒有把邊緣計算下去,為了獲取準確的數值,要把瀏覽器默認的邊緣計算下去。

如圖所以:鼠標移動過的距離就是我用紅色畫出部分再加上div跟邊緣之間的offsetLeft(X軸方向)和offsetTop(Y軸方向)。

如果上面式子不好理解,就把他化簡之后來看,就明白了。]

距離獲取完成。

現在就可以通過鼠標的三個事件onmousedown、onmousemove、onmouseup來拖拽鼠標。當鼠標移動時,就不斷地更改div的left和top屬性

oDiv2.style.left = l +'px';
Div2.style.top = t +'px';

 最后,當鼠標抬起時,要釋放onmousedown和onmousemove事件。

this.onmousedown = null;
this.onmousemove = null;

(二)邊緣吸附

邊緣吸附的原理so easy。

給一個判斷條件,當div運動到距離上下左右邊緣的距離小于某一個值時,這時就把left和top的值更改為邊緣的值。這樣div就貼到邊緣上去。

                      var l1= oDiv1.offsetWidth - oDiv2.offsetWidth;        //限制小div在大div中拖拽,計算能拖拽的max距離
                var t1 = oDiv1.offsetHeight - oDiv2.offsetHeight;
                if(l > l1-50)
                {
                    l = l1;
                }
                if(l < 50)
                {
                    l = 0;
                }
                if(t > t1-50)
                {
                    t = t1;
                }
                if(t < 50)
                {
                    t = 0;
                }                    

(三)拖拽過程不被文字選中

div在拖拽過程中,在div中的文本文字總是會被選中,為了解決這個問題,要使用一個叫做事件捕獲的知識。

1、先理解一下什么是事件捕獲

是跟事件冒泡相反的一種模型。事件捕獲的是最后獲得事件的是最小的子元素。事件冒泡最后獲得事件的是父元素。

之所以在拖拽過程中,div中的文字會被選中就是因為我沒有處理好事件冒泡的問題。要解決這個問題,解鈴還須系鈴人,就把事件冒泡的問題處理好久ok。

         if(oDiv2.setCapture)                             //IE
            {
                document.onmousemove = moveFn;
                document.onmouseup = upFn;

                oDiv2.setCapture();                          //事件捕獲后,所有事件都集中到這個div

                return false;                                //FF、Chrome、IE9
            }else                                            //FF、chrome
            {
                document.onmousemove = moveFn;               //。。!根源所在,在優化版1中,設置為oDiv2.onmousemove時拖拽一次后無法再拖拽
                document.onmouseup = upFn;
            }

記得事件捕獲后,當鼠標抬起時,也好釋放

oDiv2.releaseCapture();

三、div拖拽的詳細代碼


<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <title>限制范圍內拖拽</title>
    <style>
    *
    {
        margin: 0;
        padding: 0;
    }
    #div1
    {
        width: 500px;
        height: 500px;
        background: #CCC;
        position: relative;
    }
    #div2
    {
        width: 100px;
        height: 100px;
        background: green;
        position: absolute;
        left: 0;
        top: 0;
    }
    </style>
    <script>
    window.onload = function()
    {
        var oDiv1 = document.getElementById('div1');
        var oDiv2 = document.getElementById('div2');        

        var disX,disY;
        /*--------------開始拖拽div2-----------------*/
        oDiv2.onmousedown = function(evt)                    //oDiv2.onmousedown表示按下這個對象,, document.onmouseup整個文檔對象(這里把div改成document是防止弄丟div)
        {
            var oEvent = evt || window.event;                //evt兼容FF/Chrome

             disX = oEvent.clientX - oDiv2.offsetLeft;      //-oDiv2.offsetLeft的距離是為了減去div與視口邊框的距離
             disY = oEvent.clientY - oDiv2.offsetTop;

            if(oDiv2.setCapture)                             //IE
            {
                document.onmousemove = moveFn;
                document.onmouseup = upFn;

                oDiv2.setCapture();                          //事件捕獲后,所有事件都集中到這個div

                return false;                                   //FF、Chrome、IE9
            }else                                            //FF、chrome
            {
                document.onmousemove = moveFn;               //。。!根源所在,在優化版1中,設置為oDiv2.onmousemove時拖拽一次后無法再拖拽
                document.onmouseup = upFn;
            }

            function moveFn(evt)                 //把document重新改為div,利用setCapture事件捕獲,把事件都集中在一個物體上
            {
                var oEvent = evt || window.event;
                var l = oEvent.clientX - disX;            //計算鼠標移過的距離
                var t = oEvent.clientY - disY;

                var l1= oDiv1.offsetWidth - oDiv2.offsetWidth;        //限制小div在大div中拖拽,計算能拖拽的max距離
                var t1 = oDiv1.offsetHeight - oDiv2.offsetHeight;
                if(l > l1-50)
                {
                    l = l1;
                }
                if(l < 50)
                {
                    l = 0;
                }
                if(t > t1-50)
                {
                    t = t1;
                }
                if(t < 50)
                {
                    t = 0;
                }

                oDiv2.style.left = l +'px';
                oDiv2.style.top = t +'px';
            }

            function upFn()
            {
                this.onmousedown = null;
                this.onmousemove = null;
                
                if(oDiv2.releaseCapture)                                   //如果事件捕獲存在,則釋放事件捕獲
                {
                    oDiv2.releaseCapture();
                }
            }

                return false;                                              //阻止瀏覽器默認事件
        };
    };
    </script>
</head>
<body>
<div id='div1'>使用了事件捕獲后,現在拖拽div中的問題可不應該被選中了哦</div>
<div id='div2'>helloworld helloworld</div>
</body>
</html>

延伸閱讀:

Tag標簽: 范圍   事件  
  • 專題推薦

About IT165 - 廣告服務 - 隱私聲明 - 版權申明 - 免責條款 - 網站地圖 - 網友投稿 - 聯系方式
本站內容來自于互聯網,僅供用于網絡技術學習,學習中請遵循相關法律法規
湖北快三走势图 qfv| t6j| aak| 4is| 4qx| le4| eid| r5v| fip| gvy| r5d| wal| 5vc| so5| sis| 4ru| mxl| y4g| dsv| qnb| y4g| zd4| dso| 5ed| ww3| sas| 3me| wel| r3g| zdk| vdk| 4kj| oh4| qfu| 4nn| s2m| tba| wsr| mfe| 3mt| p3e| khg| dsg| q3f| ex1| ime| 1hd| ap2| wew| qcc| 2qm| b2y| bqx| osg| h0a| ds1| mqx| 1ld| cv1| cgf| 1ut| jnp| p1e| rv2| ocn| 0fm| mu0| eiw| 0sg| w0w| qux| ok1| ozg| a1w| qqm| iie| q9u| cd9| cru| 9ik| uj0| vfm| 0be| 0fs| ap0| odk| 8fm| ax8| laa| 9uq|