1. 程式人生 > >實現div在固定區域跟隨鼠標移動點擊拖動而產生的變化

實現div在固定區域跟隨鼠標移動點擊拖動而產生的變化

DPoS parseint func order dshow loop 指定 鼠標移動 border

一、思路

1.在外層增加一個 DIV 容器,並設置好容器的大小。(即:寬和高)

當容器存在邊框的時候,由於這裏還沒找到獲取的方法,所以,在容器邊框大於 0 的時候,獲得的容器的限制區域的坐標會有誤差。

為了避免這情況,可以在多加一次容器,有邊框樣式的在外層,無邊框樣子的在內層。

例:

<style>
    #mainContainer {
        border: 10px solid #990000;
        width: 600px;
        height: 300px;
    }

    #innerContainer {
        width: 100%;
        height: 100%;
    }

    #Drag {
        /*border: 5px solid #C4E3FD;*/
        background: #C4E3FD;
        width: 50px;
        height: 50px;
        top: 50px;
        left: 50px;
        z-index: 2;
    }

    #Drag2 {
        /*border: 5px solid #C4E3FD;*/
        background: #ff0000;
        width: 50px;
        height: 50px;
        top: 50px;
        left: 50px;
        z-index: 3;
    }
</style>

<div id="mainContainer">
    <div id="innerContainer">
        <div id="Drag" onmousedown="moveBind(this, event)">1</div>
        <div id="Drag2" onmousedown="moveBind(this, event)">2</div>
    </div>
</div>
<br />拖放狀態:<span id="idShow">未開始</span>

2.為了方便獲得元素的位置和大小,先寫一個方法來輔助(谷歌不能用了可惡orz,只能百度出這個方法並稍微做點修改)。

    //獲得元素的坐標與大小。
    function findPosition(oElement) {
        var x2 = 0;
        var y2 = 0;
        var width = oElement.clientWidth;
        var height = oElement.clientHeight;
        //alert(width + "=" + height);
        if (typeof (oElement.offsetParent) != ‘undefined‘) {
            for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) {
                posX += oElement.offsetLeft;
                posY += oElement.offsetTop;
            }
            x2 = posX + width;
            y2 = posY + height;
            return [posX, posY, x2, y2, width, height];

        } else {
            x2 = oElement.x + width;
            y2 = oElement.y + height;
            return [oElement.x, oElement.y, x2, y2, width, height];
        }
    }

這裏以數組的形式返回元素的 X 開始坐標和 Y 開始坐標,X 結束坐標和 Y 結束坐標,元素真實的寬與高(不算邊框)

3.在鼠標按下事件裏,先獲得容器的位置數據:

//獲得容器坐標。
var container = findPosition(document.getElementById("innerContainer"));
var containerLeft = container[0];
var containerTop = container[1];
var containerWidth = container[4];
var containerHeight = container[5];

4.計算拖動 DIV 元素可移動的區域坐標:

/*計算出容器的範圍坐標。*/

//開始 X 坐標。
var startX = containerLeft;
//開始 Y 坐標。
var startY = containerTop;
//結束 X 坐標。
var maxX = startX + containerWidth - width;
//結束 Y 坐標。
var maxY = startY + containerHeight - height;

開始 X 坐標 = 容器的左上角 X 坐標。

開始 Y 坐標 = 容器的左上角 Y 坐標。

結束 X 坐標 = 開始 X 坐標 + 容器的寬度 - 拖動 DIV 元素的寬度

結束 Y 坐標 = 開始 Y 坐標 + 容器的高度 - 拖動 DIV 元素的高度

5.當區域內存在多個可拖動的 DIV 元素時,要把當前鼠標點擊的那個 DIV 設置成置頂顯示。

    //獲得最大 Z 坐標。
    function getMaxIndex() {
        var index = 0;
        var ds = document.getElementById(‘innerContainer‘).getElementsByTagName(‘div‘);
        var length = document.getElementById(‘innerContainer‘).getElementsByTagName(‘div‘).length;

        for (var loop = 0; loop < length; loop++) {
            if (ds[loop].style.zIndex > index) index = ds[loop].style.zIndex;
        }

        return parseInt(index);
    }

該方法遍歷容器內的所有 DIV 元素(即:可拖動元素),取得它們當中z-Index最大的值。

然後,設置點擊元素的 z-Index 值:

//鼠標選中的元素設置成頂層。
obj.style.zIndex = getMaxIndex() + 1;

/*******************以上方法是在鼠標按下事件裏 onmousedown ******************/

/*******************以下方法是在鼠標按下事件裏 onmousemove ******************/

6.在移動事件裏,修改元素位置的外層加上如下這條件。

            //不可以超出指定的範圍。
            if (moveLeft >= startX && moveTop >= startY && moveLeft <= maxX && moveTop <= maxY) {
                //當移動位置在範圍內時,元素跟隨鼠標移動。
                obj.style.left = moveLeft + "px";
                obj.style.top = moveTop + "px";
            }

這條件表示:移動的位置在容器範圍內時,元素才可以跟隨鼠標移動。

但是,現在這樣的做法,當鼠標快速拖出容器區域時,元素就會停止不動,但並沒有移動到最邊界,同時,鼠標在區域外並沒有放開按鍵,移動鼠標時元素並不會跟著移動。

解決的思路是:

(1)當元素水平(X坐標)移動的位置沒有達到或超出容器限制區域的 X 坐標區域時。

繼續修改拖動元素的 X 坐標位置。

(2)當元素水平(X坐標)移動的位置超出容器限制區域的最大 X 坐標(即:容器右下角的 X 坐標)區域時(即:限制區域的右邊),將元素的 X 坐標設置成最大 X 坐標值。

if (moveLeft >= startX && moveLeft <= maxX) {
                    obj.style.left = moveLeft + "px";
                } else if (moveLeft > maxX) {
                    obj.style.left = maxX + "px";
                }

(3)當元素水平(X坐標)移動的位置小於容器限制區域的開始 X 坐標(即:容器左上角的 X 坐標)區域時(即:限制區域的左邊),將元素的 X 坐標設置成最小 X 坐標值。

                if (moveLeft >= startX && moveLeft <= maxX) {
                    obj.style.left = moveLeft + "px";
                } else if (moveLeft > maxX) {
                    obj.style.left = maxX + "px";
                } else if (moveLeft < startX) {
                    obj.style.left = startX + "px";
                }

(4)Y 坐標同以上(1)(2)(3):

                if (moveTop >= startY && moveTop <= maxY) {
                    obj.style.top = moveTop + "px";
                } else if (moveTop > maxY) {
                    obj.style.top = maxY + "px";
                } else if (moveTop < startY) {
                    obj.style.top = startY + "px";
                }

完成了!這時,鼠標拖動到區域外面時,元素同樣會跟隨鼠標的位置在容器內移動。

二、以下是完整源碼:

JS部分:

    //獲得元素的坐標與大小。
    function findPosition(oElement) {
        var x2 = 0;
        var y2 = 0;
        var width = oElement.clientWidth;
        var height = oElement.clientHeight;
        //alert(width + "=" + height);
        if (typeof (oElement.offsetParent) != ‘undefined‘) {
            for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) {
                posX += oElement.offsetLeft;
                posY += oElement.offsetTop;
            }
            x2 = posX + width;
            y2 = posY + height;
            return [posX, posY, x2, y2, width, height];

        } else {
            x2 = oElement.x + width;
            y2 = oElement.y + height;
            return [oElement.x, oElement.y, x2, y2, width, height];
        }
    }

    function moveBind(obj, evnt) {
        //獲得元素坐標。
        var left = obj.offsetLeft;
        var top = obj.offsetTop;
        var width = obj.offsetWidth;
        var height = obj.offsetHeight;

        //計算出鼠標的位置與元素位置的差值。
        var cleft = evnt.clientX - left;
        var ctop = evnt.clientY - top;

        //獲得容器坐標。
        var container = findPosition(document.getElementById("innerContainer"));
        var containerLeft = container[0];
        var containerTop = container[1];
        var containerWidth = container[4];
        var containerHeight = container[5];

        /*計算出容器的範圍坐標。*/

        //開始 X 坐標。
        var startX = containerLeft;
        //開始 Y 坐標。
        var startY = containerTop;
        //結束 X 坐標。
        var maxX = startX + containerWidth - width;
        //結束 Y 坐標。
        var maxY = startY + containerHeight - height;

        //鼠標選中的元素設置成頂層。
        obj.style.zIndex = getMaxIndex() + 1;

        //輸出顯示。
        //show("idShow", startX, startY);

        document.onmousemove = function (doc) {
            //計算出移動後的坐標。
            var moveLeft = doc.clientX - cleft;
            var moveTop = doc.clientY - ctop;

            //設置成絕對定位,讓元素可以移動。
            obj.style.position = "absolute";

            //不可以超出指定的範圍。
            if (moveLeft >= startX && moveTop >= startY && moveLeft <= maxX && moveTop <= maxY) {
                //當移動位置在範圍內時,元素跟隨鼠標移動。
                obj.style.left = moveLeft + "px";
                obj.style.top = moveTop + "px";
            } else {
                /****************以下為處理當鼠標的位置不在範圍內裏,鼠標的移動,裏面的元素也要跟著移動*****************/
                //向右移動時,如果移動坐標沒有大於最大 X 坐標,則移動,否則設置成最大 X 坐標的值。
                if (moveLeft >= startX && moveLeft <= maxX) {
                    obj.style.left = moveLeft + "px";
                } else if (moveLeft > maxX) {
                    obj.style.left = maxX + "px";
                } else if (moveLeft < startX) {
                    obj.style.left = startX + "px";
                }

                //向下移動時,如果移動坐標沒有大於最大 Y 坐標,則移動,否則設置成最大 Y 坐標的值。
                if (moveTop >= startY && moveTop <= maxY) {
                    obj.style.top = moveTop + "px";
                } else if (moveTop > maxY) {
                    obj.style.top = maxY + "px";
                } else if (moveTop < startY) {
                    obj.style.top = startY + "px";
                }
            }

            show("idShow", moveLeft, moveTop);
        }

        document.onmouseup = function () {
            document.onmousemove = function () { }
        };
    }

    //獲得最大 Z 坐標。
    function getMaxIndex() {
        var index = 0;
        var ds = document.getElementById(‘innerContainer‘).getElementsByTagName(‘div‘);
        var length = document.getElementById(‘innerContainer‘).getElementsByTagName(‘div‘).length;

        for (var loop = 0; loop < length; loop++) {
            if (ds[loop].style.zIndex > index) index = ds[loop].style.zIndex;
        }

        return parseInt(index);
    }

    //顯示坐標信息。
    function show(id, x, y) {
        document.getElementById(id).innerHTML = "left:" + x + ";top:" + y;
    }

HTML部分:

<style>
    #mainContainer {
        border: 10px solid #990000;
        width: 600px;
        height: 300px;
    }

    #innerContainer {
        width: 100%;
        height: 100%;
    }

    #Drag {
        /*border: 5px solid #C4E3FD;*/
        background: #C4E3FD;
        width: 50px;
        height: 50px;
        top: 50px;
        left: 50px;
        z-index: 2;
    }

    #Drag2 {
        /*border: 5px solid #C4E3FD;*/
        background: #ff0000;
        width: 50px;
        height: 50px;
        top: 50px;
        left: 50px;
        z-index: 3;
    }
</style>

<div id="mainContainer">
    <div id="innerContainer">
        <div id="Drag" onmousedown="moveBind(this, event)">1</div>
        <div id="Drag2" onmousedown="moveBind(this, event)">2</div>
    </div>
</div>
<br />拖放狀態:<span id="idShow">未開始</span>

實現div在固定區域跟隨鼠標移動點擊拖動而產生的變化