2011-02-09 33 views
16

Me gustaría mover un div con mis teclas de flecha usando jQuery. Así que derecha, izquierda, abajo y arriba.cómo mover un div con las teclas de flecha

Encontrado un demo de lo que quiero lograr here

me gustaría ser capaz de moverse alrededor de un div en otro div.

¿Cómo se puede hacer esto?

+1

1) Crear HTML y CSS con posición absoluta 'div'. 2) Se presionan las teclas de flecha de seguimiento. 3) Cambie las propiedades CSS 'top' y' left' de div según corresponda. ¿Con cuál de estos tienes problemas? – Phrogz

+0

Número 2 porque no sé cómo puedo vincular las teclas de flecha a un div – Opoe

+0

Has publicado un ejemplo en tu pregunta ... con código ... ¿qué necesitas de nosotros? – Rabbott

Respuesta

34

HTML:

<div id="pane"> 
    <div id="box"></div> 
</div> 

CSS:

#pane { 
    position:relative; 
    width:300px; height:300px; 
    border:2px solid red; 
} 

#box { 
    position:absolute; top:140px; left:140px; 
    width:20px; height:20px;   
    background-color:black; 
} 

JavaScript:

var pane = $('#pane'), 
    box = $('#box'), 
    w = pane.width() - box.width(), 
    d = {}, 
    x = 3; 

function newv(v,a,b) { 
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0); 
    return n < 0 ? 0 : n > w ? w : n; 
} 

$(window).keydown(function(e) { d[e.which] = true; }); 
$(window).keyup(function(e) { d[e.which] = false; }); 

setInterval(function() { 
    box.css({ 
     left: function(i,v) { return newv(v, 37, 39); }, 
     top: function(i,v) { return newv(v, 38, 40); } 
    }); 
}, 20); 

explicaciones variables:
w - la máxima izquierda/superior valor que el cuadro puede tener (para mantenerse dentro de los límites)
x - la distancia (en px) que se mueve el cuadro en cada intervalo
d - este objeto almacena la información sobre qué tecla se está presionando. Por ejemplo, mientras el usuario mantiene presionada la tecla FLECHA IZQUIERDA, d['37'] es true. De lo contrario, es false. Por cierto, 37 es el código de tecla para la tecla FLECHA IZQUIERDA y este valor se almacena en la propiedad e.which del objeto de evento. El objeto d se está actualizando en cada evento keydown y keyup.

Un setInterval que se ejecuta cada 20 ms, actualiza las propiedades CSS izquierda y superior del elemento box. Los nuevos valores se calculan a través de la función newv.

La función newv calculará el nuevo valor a la izquierda/arriba basado en a) el valor anterior v yb) el objeto d.

La expresión n < 0 ? 0 : n > w ? w : n asegura que el nuevo valor está en los límites permitidos (que son 0 to w). Si n es < 0, se devolverá cero. Si n es> w, se devolverá w.


Demostración en directo: http://jsfiddle.net/simevidas/bDMnX/1299/


Actualización: Este código tiene la misma funcionalidad que el código original anterior. La única diferencia es que utilicé nombres más significativos para mis variables y argumentos. Como puede ver, se ve horrible: la versión original es claramente mejor. :P

var pane = $('#pane'), 
    box = $('#box'), 
    maxValue = pane.width() - box.width(), 
    keysPressed = {}, 
    distancePerIteration = 3; 

function calculateNewValue(oldValue, keyCode1, keyCode2) { 
    var newValue = parseInt(oldValue, 10) 
        - (keysPressed[keyCode1] ? distancePerIteration : 0) 
        + (keysPressed[keyCode2] ? distancePerIteration : 0); 
    return newValue < 0 ? 0 : newValue > maxValue ? maxValue : newValue; 
} 

$(window).keydown(function(event) { keysPressed[event.which] = true; }); 
$(window).keyup(function(event) { keysPressed[event.which] = false; }); 

setInterval(function() { 
    box.css({ 
     left: function(index ,oldValue) { 
      return calculateNewValue(oldValue, 37, 39); 
     }, 
     top: function(index, oldValue) { 
      return calculateNewValue(oldValue, 38, 40); 
     } 
    }); 
}, 20); 
+4

Sin falta de respeto, pero a pesar de que este código funciona maravillosamente (es realmente agradable), los nombres de las variables me hacen sentir como si fuera una competencia de código ofuscado. Leer el código es difícil porque nada tiene un nombre significativo que no sea 'pane 'y' box' (y los operadores ternarios apilados no ayudan). Pero como dije, funciona muy bien. – Reid

+0

@Reid ¿No están limpios los operadores ternarios apilados? ':)' Una vez que descubras lo que hacen, te volará la cabeza, jeje. Pero, sí, probablemente debería dar una explicación de mi código. Dame un segundo ... –

+0

@ime Vidas Te subí de todas maneras, pero creo que usar nombres de variable más claros sería mejor que explicar los de tu personaje :) – alex

3

no puedo ver su demostración, pero aquí es un simple "mover el cuadro de 1px en la dirección de las flechas" ejemplo:

CSS:

#wrapper { 
    background-color: gray; 
    height:200px; 
    width: 200px; 
    position:absolute; 
} 
#mover { 
    background-color: white; 
    border: 1px solid red; 
    height:20px; 
    width: 20px; 
    position:relative; 
} 

de marcado:

<div id="wrapper"> 
    <div id="mover"></div> 
</div> 

JS (usando jQuery):

$("#wrapper").keydown(function(event) { 
    var $mover = $("#mover"); 
    //if nothing else will move "mover", then track the 
    //position instead of recalculating it every time: 
    // var moverPos = $mover.position(); 
    // var left = moverPos.left; 
    // var top = moverPos.top; 
    var addTop = function(diff) { 
     $mover.css("top", ($mover.position().top + diff) + "px"); 
     //if using tracked position: 
     // top += diff; 
     // $mover.css("top", top) + "px"); 
    }; 

    var addLeft = function(diff) { 
     $mover.css("left", ($mover.position().left + diff) + "px"); 
     //if using tracked position: 
     // left += diff; 
     // $mover.css("left", left) + "px"); 
    }; 

    switch(event.keyCode) { 
     case 37: //left 
      addLeft(-1); break; 
     case 38: //up 
      addTop(-1); break; 
     case 39: //right 
      addLeft(1); break; 
     case 40: //down 
      addTop(1); break; 
    } 
}); 

Esto es solo un ejemplo, es posible que desee agregar comprobación de límites, movimientos más grandes, animación más suave, soporte de teclado numérico o cualquier cantidad de cosas más, pero debe comenzar.

4

@ Šime Vidas: su primera solución es sencillamente maravillosa. (Creo que el segundo es redundante =)

¿Puedo sugerir hacer dos funciones diferentes para el ancho vertical y horizontal? Debido a que es muy poco probable que usted tiene que moverse alrededor de un div dentro de un cuadrado perfecto y creo que sería mejor tener algo como esto:

$(function() { 
var pane = $('#pane'), 
box = $('#box'), 
wh = pane.width() - box.width(), 
wv = pane.height() - box.height(), 
d = {}, 
x = 5; 

function newh(v,a,b) { 
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0); 
    return n < 0 ? 0 : n > wh ? wh : n; 
} 

function newv(v,a,b) { 
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0); 
    return n < 0 ? 0 : n > wv ? wv : n; 
} 

$(window).keydown(function(e) { d[e.which] = true; }); 
$(window).keyup(function(e) { d[e.which] = false; }); 

setInterval(function() { 
    box.css({ 
     left: function(i,v) { return newh(v, 37, 39); }, 
     top: function(i,v) { return newv(v, 38, 40); } 
    }); 
}, 20); 
}); 

Esto habría sido exactamente lo que estaba buscando.

Si tuviera un diseño de respuesta basada en los valores% sería recomendable ajustar su setInterval así:

setInterval(function() { 
    box.css({ 
     left: function(i,v) { return newh(v, 37, 39); }, 
     top: function(i,v) { return newv(v, 38, 40); } 
    }); 
    wh = pane.width() - box.width(); 
    wv = pane.height() - box.height(); 
}, 20); 

si lo hace que ajusta su altura paneles y la anchura y la caja todavía se detiene en su frontera.

hice un violín de eso aquí http://jsfiddle.net/infidel/JkQrR/1/

muchas gracias.

+0

Esto es exactamente lo que estaba buscando. ¡Tu respuesta necesita más votos positivos! – Mav

0

probar este Código

<html> 
<head> 
    <style> 
      #ss{ 
       background:#ccc; 
       height:100px; 
       width:100px; 
       position: absolute; 
       top: 0; 
       left: 0; 
      } 
    </style> 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"> 
    </script> 
</head> 
<body> 
    <div id="ss"></div> 
</body> 

<script type="text/javascript">  
var $div = $('#ss'); 
$(document).keydown(function(e) { 
    switch (e.which) { 
     case 37: 
       $div.css('left', $div.offset().left - 10); 
       break; 
     case 38: 
       $div.css('top', $div.offset().top - 10); 
       break; 
     case 39: 
       $div.css('left', $div.offset().left + 10); 
       break; 
     case 40: 
       $div.css('top', $div.offset().top + 10); 
       break; 
     } 
    }) 
</script> 

</html> 
Cuestiones relacionadas