這篇將介紹網頁中元素如何實現拖拽效果。
讓元素在頁面中移動,其實并不復雜,總體思想是分為以下幾點。
1.重載頁面中的mouse事件。
2.告訴頁面那些元素可以移動。
3.獲取鼠標和元素在頁面中的坐標值。
4.改變元素的坐標值使其移動。
以上篇制作象棋棋盤為基礎,來介紹程序如何實現。
在<div id="chessboard"></div>的最下面添加一個div元素。
如:
<div id="chessboard">


<div id="helpContainer" style="position:absolute;display:none;z-index:10"></div>
</div>
添加這個元素的作用是為了使被拖拽元素在拖拽時顯示在所有棋子之上所使用的臨時元素。
首先我們要重載需要移動元素的onmousedown事件。當鼠標點擊item時就把當前item賦給javascript中的全局變量dragObject,即告訴了頁面需要移動的是哪個item。
并且取得了當前鼠標相對于item的坐標,以在移動元素時使用。
var dragObject = null;
var mouseOffset = null;
var helpContainer = null;
var parentTarget = null;
Number.prototype.NaN0=function(){return isNaN(this)?0:this;}
//重載需要移動的item的onmousedown事件
function makeDragDropable(item){
if(!item) return;
item.onmousedown = function(ev){
dragObject = this;
mouseOffset = getMouseOffset(this, ev);
if(dragObject)
helpContainer.appendChild(dragObject.cloneNode(true)); //克隆元素到helpContainer里
parentTarget = dragObject.parentNode;
return false;
};
}
//取得鼠標相對于item的坐標
function getMouseOffset(target, ev){
ev = ev || window.event; //ev在Firefox中只能被當前函數獲取,而在IE里是全局變局
var docPos = getPosition(target);
var mousePos = mouseCoords(ev);
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}
//item相對于整個document的絕對坐標
function getPosition(e){
var left = 0;
var top = 0;
while(e.offsetParent){
left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
e = e.offsetParent;
}
left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
return {x:left, y:top};
}
//mouse相對于整個document的絕對坐標
function mouseCoords(ev){
if(ev.pageX || ev.pageY){
return {x:ev.pageX, y:ev.pageY};
}
return {x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
y:ev.clientY + document.body.scrollTop - document.body.clientTop};
}
window.onload = function(){
helpContainer = document.getElementById("helpContainer");
boardPos = getPosition(document.getElementById("chessboard"));
makeDragDropable(document.getElementById("zhu_0_0")); //使“車”這個棋子擁有了拖拽的基礎,其它棋子的拖拽添加方法一樣。
}
需要的信息都取得了,為了使item移動,必需重載頁面的onmousemove事件。
document.onmousemove = mouseMove;
function mouseMove(ev){
ev = ev || window.event;
var target = ev.target || ev.srcElement;
var mousePos = mouseCoords(ev);
//隱藏當前元素,顯示help臨時元素
helpContainer.style.display = "";
dragObject.style.display = "none";
//移動help元素
helpContainer.style.top = mousePos.y - mouseOffset.y - boardPos.y;
helpContainer.style.left = mousePos.x - mouseOffset.x - boardPos.x;
}
到這里移動元素的功能就實現了,但在下象棋時棋子只能在格子的十字中心的位置上。
下面我就介紹如何給棋子添加定位功能。
重載onmouseup事件,即在鼠標提起時所觸發的事件。
document.onmouseup = mouseUp;
function mouseUp(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
var dLength = dropTargets.length;
//判斷當前棋子是否在可走集合內
for(var i = 0; i < dLength; i++){
curTarget = dropTargets[i];
curTargetPos = getPosition(curTarget);
curTargetWidth = parseInt(curTarget.offsetWidth);
curTargetHeight = parseInt(curTarget.offsetHeight);
if(mousePos.x > curTargetPos.x
&& mousePos.x < (curTargetPos.x + curTargetWidth)
&& mousePos.y > curTargetPos.y
&& mousePos.y < (curTargetPos.y + curTargetHeight)){
resetChessmanPos();
if(eatChessman(curTarget)){
//目標元素添加被拖拽棋子
curTarget.appendChild(dragObject);
}
curTarget = null;
}else{
resetChessmanPos();
}
}
dragObject = null;
}
//是否可以吃棋子
function eatChessman(curTarget){
var obj = curTarget.firstChild;
if(!obj) return true;
if(dragObject){
var temp = obj.id.split("_");
var temp2 = dragObject.id.split("_");
if(temp[1] == temp2[1]){
dragObject.style.top = 0;
dragObject.style.left = 0;
return false;
}else{
//eatContainer.appendChild(obj);
return true;
}
}
return false;
}
//重設棋子坐標
function resetChessmanPos(){
dragObject.style.top = 0;
dragObject.style.left = 0;
dragObject.style.display = "";
helpContainer.style.display = "none";
}
var dropTargets = [];
function addDragDropTarget(dropTarget){
dropTargets.push(dropTarget);
}
window.onload = function(){
//在已有的代碼中添加如下代碼
for(var row = 0; row < 10; row++){
for(var col = 0; col < 9; col++){
//添加棋子可走范圍集合
addDragDropTarget(document.getElementById("grid_"+row+"_"+col));
}
}
}
棋子拖拽的功能基本上完成了。
不過象棋是有規則的哦,下面把規則加進去。
function chessRule(curTarget){
var pTemp = parentTarget.id.split("_");
var dTemp = dragObject.id.split("_")[0];
var uTemp = dragObject.id.split("_")[1];
var cTemp = curTarget.id.split("_");
var y1 = cTemp[1];
var x1 = cTemp[2];
var y2 = pTemp[1];
var x2 = pTemp[2];
switch(dTemp){
case "zhu":
if(x1 == x2 || y1 == y2){
if(x1 == x2){
return !isBlock(x1, y1, y2, "y");
}
if(y1 == y2){
return !isBlock(y1, x1, x2, "x");
}
}else{
return false;
}
break;
case "ma":
var n = new Array(1, 2, 2, 1, -1, -2, -2, -1);
var m = new Array(-2, -1, 1, 2, 2, 1, -1, -2);
for(var i = 0; i < 8; i++){
if((n[i]+parseInt(y2)) == y1 && (m[i]+parseInt(x2)) == x1){
if(Math.abs(n[i]) > Math.abs(m[i])){
var obj = document.getElementById("grid_"+(parseInt(y2)+n[i]/2)+"_"+x2);
if(obj.firstChild)
return false;
else
return true;
}else{
var obj = document.getElementById("grid_"+y2+"_"+(parseInt(x2)+m[i]/2));
if(obj.firstChild)
return false;
else
return true;
}
}
}
return false;
break;
case "xiang":
if(uTemp == 0 && y1 > 4){
return false;
}else if(uTemp == 1 && y1 < 5){
return false;
}else{
var n = new Array(2, 2, -2, -2);
var m = new Array(-2, 2, 2, -2);
return loopPos(x1, y1, x2, y2, n, m);
}
break;
case "shi":
var n = new Array(-1, 1, -1, 1);
var m = new Array(-1, -1, 1, 1);
if(x1 < 3 || x1 > 5){
return false;
}else if(uTemp == 0 && y1 > 2){
return false;
}else if(uTemp == 1 && y1 < 7){
return false;
}else{
return loopPos(x1, y1, x2, y2, n, m);
}
break;
case "jiang":
case "shuai":
var n = new Array(0, 1, 0, -1);
var m = new Array(-1, 0, 1, 0);
if(x1 < 3 || x1 > 5){
return false;
}else if(uTemp == 0 && y1 > 2){
return false;
}else if(uTemp == 1 && y1 < 7){
return false;
}else{
return loopPos(x1, y1, x2, y2, n, m);
}
break;
case "pao":
if(x2 == x1 || y2 == y1){
if(x2 == x1){
if(isBlock(x1, y1, y2, "y") && isEat(curTarget, uTemp)){
return true;
}else if(!isBlock(x1, y1, y2, "y") && isEat(curTarget, uTemp)){
return false;
}else if(isBlock(x1, y1, y2, "y") && !isEat(curTarget, uTemp)){
return false;
}
return true;
}else if(y2 == y1){
if(isBlock(y1, x1, x2, "x") && isEat(curTarget, uTemp)){
return true;
}else if(!isBlock(y1, x1, x2, "x") && isEat(curTarget, uTemp)){
return false;
}else if(isBlock(y1, x1, x2, "x") && !isEat(curTarget, uTemp)){
return false;
}
return true;
}
}else{
return false;
}
break;
case "bing":
case "zu":
if(uTemp == 0){
if(y2 > 4){
var n = new Array(1, 0, -1);
var m = new Array(0, 1, 0);
return loopPos(x1, y1, x2, y2, n, m);
}else{
if(parseInt(x2) == x1 && (parseInt(y2)+1) == y1){
return true;
}else{
return false;
}
}
}else if(uTemp == 1){
if(y2 < 5){
var n = new Array(-1, 0, 1);
var m = new Array(0, -1, 0);
return loopPos(x1, y1, x2, y2, n, m);
}else{
if(parseInt(x2) == x1 && (parseInt(y2)-1) == y1){
return true;
}else{
return false;
}
}
}
break;
}
return true;
}
function loopPos(x1, y1, x2, y2, n, m){
var l = n.length;
for(var i = 0; i < l; i++){
if((parseInt(x2)+n[i]) == x1 && (parseInt(y2)+m[i]) == y1){
return true;
}
}
return false;
}
function isEat(curTarget, uTemp){
if(curTarget.firstChild && curTarget.firstChild.id.split("_")[1] != uTemp){
return true
}else{
return false;
}
}
function isBlock(num1, num2, num3, flag){
var t1 = Math.max(num2, num3);
var t2 = Math.min(num2, num3);
var temp = null;
for(var i = t2+1; i < t1; i++){
if(flag == "x"){
temp = document.getElementById("grid_"+num1+"_"+i);
}else{
temp = document.getElementById("grid_"+i+"_"+num1);
}
if(temp.firstChild != null)
return true;
}
return false;
}
對function mouseUp(ev)方法添加規則部分。
function mouseUp(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
var dLength = dropTargets.length;
//判斷當前棋子是否在可走集合內
for(var i = 0; i < dLength; i++){
curTarget = dropTargets[i];
curTargetPos = getPosition(curTarget);
curTargetWidth = parseInt(curTarget.offsetWidth);
curTargetHeight = parseInt(curTarget.offsetHeight);
if(mousePos.x > curTargetPos.x
&& mousePos.x < (curTargetPos.x + curTargetWidth)
&& mousePos.y > curTargetPos.y
&& mousePos.y < (curTargetPos.y + curTargetHeight)){
if(chessRule(curTarget)){
resetChessmanPos();
if(eatChessman(curTarget)){
//目標元素添加被拖拽棋子
curTarget.appendChild(dragObject);
}
curTarget = null;
}else{
resetChessmanPos();
}
}else{
resetChessmanPos();
}
}
dragObject = null;
}
前臺部分基本完成了。下一貼將介紹如何利用DWR與后臺進行交互。