Saltar al contenido

cómo mover un div con las teclas de flecha

Solución:

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);
#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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

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

Explicaciones variables:
w – el valor máximo izquierdo / superior que puede tener la caja (para mantenerse dentro de los límites)
x – la distancia (en px) que la caja se mueve 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 el e.which propiedad del objeto de evento. los d el objeto se actualiza en cada keydown y keyup evento.

Un setInterval que se ejecuta cada 20 ms, actualiza las propiedades CSS superior e izquierda del elemento de cuadro. Los nuevos valores se calculan mediante el newv función.

los newv La función calculará el nuevo valor izquierdo / superior basado en a) el valor anterior v yb) el d objeto.

La expresion n < 0 ? 0 : n > w ? w : n asegura que el nuevo valor está dentro de 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 vivo: http://jsfiddle.net/simevidas/bDMnX/1299/


Actualizar: Este código tiene la misma funcionalidad que el código original anterior. La única diferencia es que usé 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);

@ Šime Vidas: Su primera solución es simplemente maravillosa. (creo que el segundo es redundante =)

¿Puedo sugerir hacer dos funciones diferentes para el ancho vertical y horizontal? Porque es muy poco probable que tengas que moverte 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 receptivo basado en valores de%, sería recomendable ajustar su setInterval de esta manera:

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, ajusta la altura y el ancho de sus paneles y el cuadro aún se detiene en su borde.

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

Muchas gracias.

No puedo ver tu demostración, pero aquí tienes un ejemplo simple de “mover el cuadro 1 px en la dirección de las teclas de flecha”:

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;
}

Margen:

<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;
    }
});

Este es solo un ejemplo, es posible que desee agregar verificación de límites, movimientos más grandes, animación más suave, soporte de teclado numérico o cualquier cantidad de otras cosas, pero debería ayudarlo a comenzar.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *