Di chuyển đối tượng trên trang web - Phần 3

Di chuyển một đối tượng bằng cách rê thả chuột cũng khá thú vị. Nhưng còn với bàn phím thì sao ?

Chúng ta cũng có thể dùng các phím "mũi tên", hay bất kỳ phím nào đó, để điều khiển một đối tượng di chuyển trên trang web. Và dưới đây sẽ là một ví dụ.


Trên trang web này, tôi có 3 đối tượng. Khi click chuột vào 1 trong 3 đối tượng, trong hình là W, nó sẽ chuyển sang trạng thái focus, và bạn có thể dùng các phím mũi tên để di chuyển lên, xuống, sang phải, hoặc sang trái.

Phần HTML của 3 đối tượng như sau :

<pre> &lt;div id="obj1" onclick="setFocus(this.id);"&gt;  
     Q  
   &lt;/div&gt;  
   &lt;div id="obj2" onclick="setFocus(this.id);"&gt;  
     W  
   &lt;/div&gt;  
   &lt;div id="obj3" onclick="setFocus(this.id);"&gt;  
     E  
   &lt;/div&gt;  
</pre>

Và đây là các hàm JavaScript điều khiển :
 var  dragobj=null, focusObj=null, oLeft=0, oTop=0, speed=7;

function setFocus(obj){
   setBlur();
if(obj){
  dragobj = rel(obj);
  dragobj.style.backgroundColor='#ff6666';
  dragobj.style.borderStyle='dotted';
  dragobj.style.zIndex=3;
  document.onkeydown=startMove;
  document.onkeypress=moving;
  document.onkeydown=moving;
  focusObj=dragobj;
}
}
function startMove(){
  if(dragobj){
    oLeft=dragobj.offsetLeft;
    oTop=dragobj.offsetTop;
  }
}
function setBlur(){
  if(focusObj){
    focusObj.style.backgroundColor='#ff00ff';
    focusObj.style.borderStyle='double';
    focusObj.style.zIndex=1;
    focusObj=null;
  }
}
function moving(e){
    if(dragobj){
        updatePos(e);
      dragobj.style.left = oLeft + 'px';
      dragobj.style.top  = oTop + 'px';
    }
}
function updatePos(Ev) {
    oLeft=dragobj.offsetLeft;
    oTop=dragobj.offsetTop;
if (!Ev) var Ev = window.event;
  var iKeyCode = Ev.keyCode;
  if (Ev.keyCode) iKeyCode = Ev.keyCode;
  else if (Ev.which) iKeyCode = Ev.which;
    switch(iKeyCode){
        case 37 : oLeft-=speed ; break;
        case 38 : oTop-=speed ; break;
        case 39 : oLeft+=speed ; break;
        case 40 : oTop+=speed ; break;
        default : break;
    }
}


Khi chúng ta click lên 1 đối tượng, hàm setFocus được gọi cùng với tham số là ID của đối tượng đó.

setFocus bắt đầu bằng việc gỡ bỏ sự tập trung vào đối tượng đã được điều khiển trước đó. Chẳng hạn chúng ta đã nhấp vào Q, rồi nhấp sang E, trạng thái của Q phải được phục hồi. Điều này thực hiện bởi setBlur :
function setBlur(){
  if(focusObj){
    focusObj.style.backgroundColor='#ff00ff';
    focusObj.style.borderStyle='double';
    focusObj.style.zIndex=1;
    focusObj=null;
  }
}

setBlur kiểm tra biến focusObj có tồn tại hay không, nghĩa là trước đó, bạn đã điều khiển đối tượng nào khác không. Nếu có, chúng ta đặt lại một số thuộc tính định dạng cho giống với trạng thái khởi đầu. Và trả focusObj về null.

Trở lại với setFocus, chúng ta chuyển đối tượng sang trạng thái được kích hoạt cũng bằng cách thay đổi vài thiết lập CSS.

Các dòng

  document.onkeydown=startMove;
  document.onkeypress=moving;
  document.onkeydown=moving;


sẽ định nghĩa những xử lý khi ghi nhận được những tác động từ bàn phím. document.onkeydown=moving sẽ hữu dụng trong IE, còn với Mozilla thì không cần dòng này.

Cuối cùng, ta lưu đối tượng vào biến focusObj để sử dụng cho những lần kích hoạt sau.

Khi 1 phím được nhấn trên đối tượng, sự kiện onkeydown gọi hàm startMove đánh dấu khởi điểm của quá trình di chuyển đối tượng. Nó chỉ có việc xác định vị trí hiện thời của đối tượng và đưa vào 2 biến oLeft, oTop.

Nếu phím vẫn được giữ (onkeypress), chúng ta gọi hàm moving. Hàm này tính toán các giá trị oLeft, oTop rồi cập nhật vào các thuộc tính top, letf của đối tượng. Và trên màn hình chúng ta thấy đối tượng dịch chuyển.

Việc tính toán các giá trị oLeft, oTop được đảm trách bởi hàm updatePos. Hàm này nhận một đối số Ev, trong IE, Ev là một đối tượng nằm dưới lớp window - window.event, còn Netscape tự động tạo ra tham số Ev tồn tại độc lập như navigator, document...

Với IE, Ev.keyCode trả về mã của phím được nhấn. Với Netscape, mã phím nằm trong Ev.which. Đây là những con số, và trong trường hợp này chúng ta chỉ quan tâm đến 4 giá trị :


37 : Left Arrow
38 : Up Arrow
39 : Right Arrow
40 : Down Arrow


Khi phím mũi tên sang trái (Left Arrow) được nhấn, chúng ta cho đối tượng dịch chuyển về bên trái màn hình bằng cách giảm giá trị oLeft đi một khoảng bằng speed. Đây là biến được khởi tạo ban đầu, speed càng lớn thì sự di chuyển diễn ra càng nhanh.

   
case 37 : oLeft-=speed ; break;


Khi phím mũi tên sang phải (Right Arrow) được nhấn, chúng ta cho đối tượng dịch chuyển về bên phải màn hình bằng cách tăng giá trị oLeft lên.

Tương tự như vậy, chúng ta tăng hoặc giảm oTop.

Và cuối cùng, chúng ta có thể thu được kết quả như trang demo dưới đây :

http://sacroyant.googlepages.com/MovingByKey.htm



* Lưu ý :

Trong bản demo này, tôi viết thêm một hàm setObjByKeyCode nữa

function setObjByKeyCode(e) {
    if (!e) var e = window.event;
    var code;
    if (e.keyCode) code = e.keyCode;
    else if (e.which) code = e.which;
    var character = String.fromCharCode(code);
        switch(character){
            case 'q' : setFocus('obj1') ; break;
            case 'w' : setFocus('obj2') ; break;
            case 'e' : setFocus('obj3') ; break;
            default : break;
        }
}
  document.onkeypress = setObjByKeyCode;

Và sửa lại updatePos như sau :

function updatePos(Ev) {
  setObjByKeyCode(Ev);
    oLeft=dragobj.offsetLeft;
    oTop=dragobj.offsetTop;
if (!Ev) var Ev = window.event;
  var iKeyCode = Ev.keyCode;
  if (Ev.keyCode) iKeyCode = Ev.keyCode;
  else if (Ev.which) iKeyCode = Ev.which;
    switch(iKeyCode){
        case 37 : oLeft-=speed ; break;
        case 38 : oTop-=speed ; break;
        case 39 : oLeft+=speed ; break;
        case 40 : oTop+=speed ; break;
        default : break;
    }
}

Điều này cho phép người dùng có thể nhấn vào các phím Q, W, E để chọn đối tượng tương ứng. Về nguyên tác vẫn dựa trên mã phím nhập vào. Nhưng với phương thức String.fromCharCode, chúng ta xác định được ký tự mà phím đó nắm giữ.