Procurar

Categorias

Posts recentes

Arquivo

Blog feeds

Bookmarks


Drag e drop em Javascript
domingo, 3 de junho de 2007

Poder arrastar e soltar elementos HTML na página é quase sempre um grande ganho em interatividade e design, além de, em muitos casos, permitir a troca das incômodas janelas popup por divs flutuantes, que podem ser movidos pelo usuário.

Vou mostrar aqui uma forma bastante simples e funcional de fazer isso em Javascript, com três funções apenas, mas antes de mostrar o código, vou explicar a idéia da coisa e desmistificar logo o "complicadíssimo drag and drop", antes que você se decepcione com o tamanho do código…

Bem, nossas funções vão explorar três eventos: onmousedown, onmousemove e onmouseup. Essa é a anatomia do "pegar, arrastar e soltar". Mas haverá certas condições para um elemento ser arrastável, pois o script precisa saber se o elemento em foco no onmousedown deve ou não seguir o ponteiro do mouse se ele andar (onmousemove) antes do onmouseup. Para isso, estabelecemos um nome de classe (CSS) padrão que transforma o elemento num elemento arrastável e esse nome é "drag". A classe drag pode ou não existir. Aqui usamos ela para definir o cursor como "move". Além disso, é preciso definir uma variável com o ID do elemento a ser arrastado, para o caso (frequente) de arrastar um elemento a partir de outro, como uma janela é arrastada a partir de sua borda superior.

Vamos começar declarando algumas variáveis necessárias e definindo os comportamentos relativos ao mouse na função initDragDrop:

function initDragDrop() {
__dragX = 0; // cursor X
__dragY = 0; // cursor Y
__dragId = ""; // ID do el. a ser movido
__dragging = false; // true se há um el. sendo movido
document.body.onmousedown = __dragDown;
document.body.onmousemove = __dragMove;
document.body.onmouseup = function() { __dragging = false; };
}

Repare que as variáveis foram declaradas sem a instrução var, pois assim elas serão globais e estarão disponíveis para outras funções.
Sempre é melhor usar uma rotina tipo addEvent para definir os eventos. Da forma que está feito aqui, se houvesse algum comportamento definido para esses eventos, eles seriam substituídos pelos nossos.
Como trabalhamos com o elemento body, é preciso esperar o carregamento da página, portanto initDragDrop deve ser chamada no onload da página.

Desde a chamada da função acima, __dragMove passa a monitorar a variável __dragging, que só é true desde o momento em que clicamos em um elemento com a classe "drag" setada (__dragDown) até soltarmos o botão do mouse (função anônima definida para o evento onmouseup). Se __dragging é true, então passa a definir a posição do cursor para o elemento __dragEl, preservando a posição do mouse sobre o elemento.

function __dragMove(e) {
if(typeof __dragging == "undefined" || !__dragging) return;
e = e ? e : window.event;
__dragEl.style.left = (e.clientX - __dragX)+"px";
__dragEl.style.top = (e.clientY - __dragY)+"px";
};

Para __dragDown definir __dragging como true, dois testes devem ser feitos. O elemento clicado deve ter a classe drag e __dragId deve estar definido com um ID válido. Se o ID é válido, __dragEl passa a apontar para o elemento com esse ID.

function __dragDown(e) {
e = e ? e : window.event;
__dragEl = document.getElementById(__dragId) || null;
var _target = document.all ? e.srcElement : e.target;
if(!__dragEl || !(/drag/.test(_target.className))) return;
__dragX = e.clientX - __dragEl.offsetLeft;
__dragY = e.clientY - __dragEl.offsetTop;
__dragging = true;
};

Então, além da classe drag, colocaremos no elemento a ser arrastado (ou naquele que será a "alça de arraste") um comportamento no evento onmouseover definindo a variável __dragId. Veja o HTML:

<script type="text/javascript">
// tudo que foi mostrado acima …
</script>
<style type="text/css">
#Layer1 {
position:absolute;
left:20px;
top:110px;
width:100px;
height:100px;
z-index:1;
background-color: #0099CC;
}
#Layer2 {
position:absolute;
left:20px;
top:220px;
width:90px;
height:90px;
z-index:2;
background-color: #66CC99;
padding:5px;
}
#Layer3 {
width:50px;
background-color:#FFCC66;
padding:5px;
font-size:10px;
text-align:center;
}
.drag { cursor:move; }
</style>
</head>
<body onload="initDragDrop()">
<div class="drag" id="Layer1" onmouseover="__dragId = ‘Layer1′"></div>
<div id="Layer2"><div id="Layer3" class="drag" onmouseover="__dragId = ‘Layer2′">move</div></div>
<p>Drag e drop - exemplo</p>
</body>
</html>

Note que o primeiro div no mouseover aponta para si mesmo, enquanto o segundo será movido a partir do div com ID "Layer3".

Simples demais, não? Veja aqui uma página de testes.

Abraço, Cau Guanabara.

2 Comentários »

Feeds para os comentários nesse post:
TrackBack: http://cauguanabara.blogsome.com/2007/06/03/drag-e-drop-em-javascript/trackback/

  1. Opa. Valeus pelo ótimo código Cau. :)

    Por Micox em 2007-06-03 12:01:50, domingo

  2. Valeu Mico. Pode acreditar: é um grande prazer compartilhar, principalmente quando vemos algum retorno por isso (como o seu comentário).
    Abraço

    Por Cau Guanabara em 2007-06-03 12:01:50, domingo

Say something! »















Por favor digite o texto da imagem acima.

lamp! Mapa do site
Drag e drop em Javascript