實現div在固定區域跟隨鼠標移動點擊拖動而產生的變化
一、思路
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在固定區域跟隨鼠標移動點擊拖動而產生的變化