2011-12-16 17 views
7

Estoy buscando la manera más rápida y más liviana de arrastrar y soltar formas y sprites en un lienzo JS para fines de desarrollo de juegos.código más limpio de arrastrar y soltar en JavaScript Canvas

Comencé haciendo comprobaciones de distancia usando la posición actual del mouse y los orígenes de los círculos. Funciona, pero cuando se superponen tenemos problemas y no sé qué tan bien funcionará cuando se prueben múltiples sprites y otras formas aún en cada 'frame'.

¡Se agradecen todos los comentarios o sugerencias para mejores métodos!

Prefiero no utilizar una biblioteca como jQuery ya que voy por la velocidad y la ligereza y, por supuesto, ¡para aprender los métodos reales! Aquí es donde estoy:

//add the canvas listeners and functions 

canvas.addEventListener("mousemove",mousemove); 
canvas.addEventListener("mousedown",mousedown); 
canvas.addEventListener("mouseup",mouseup); 

function mousemove(e){ 
    mouseX = e.layerX - canvas.offsetLeft; 
    mouseY = e.layerY - canvas.offsetTop; 

//for each circle stored in my array of Circle objects, is my mouse within its'   
//bounds? If so, set the circles' (X,Y) to my mouse's (X,Y) 

    for(i=0;i<circArray.length;i++){ 
     dx = mouseX - circArray[i].x; 
     dy = mouseY - circArray[i].y; 
     dist = Math.sqrt((dx*dx) + (dy*dy)); 
     if(draggable && dist < circArray[i].r){   
      circArray[i].x = mouseX; 
      circArray[i].y = mouseY; 
     } 
    } 
} 

function mousedown(){ 
     draggable = true; 
} 

function mouseup(){ 
     draggable = false; 
} 
+1

Estás pensando en las arrastrables de jQuery UI (http://jqueryui.com/demos/draggable/). Incluso si no va con jQuery, le recomiendo consultar una versión no miniaturizada y ver qué hacen. Los desarrolladores definitivamente han pensado en algunos de estos problemas de rendimiento. Debido a la licencia liberal, es probable que pueda cortar una pequeña parte de la base de código. – buley

+1

Es posible que desee consultar [fabric.js] (https://github.com/kangax/fabric.js). Aquí hay una demostración: http://kangax.github.com/fabric.js/stickman/ –

Respuesta

3

Esta es la configuración que he usado para arrastrar un solo elemento. No puedo decir si quieres arrastrar varias cosas o no, eso sería una pequeña modificación.

En palabras: en mousedown buscar un objeto hit en el orden reservado que dibujó los objetos (para que el elemento superior sea golpeado primero), almacenar este elemento hit, entonces mousedrag simplemente está conectando los coords/delta a ese elemento.

//start with only the mousedown event attached 
canvas.addEventListener("mousedown",mousedown); 

//and some vars to track the dragged item 
var dragIdx = -1; 
var dragOffsetX, dragOffsetY; 

function mousedown(e){ 
    //...calc coords into mouseX, mouseY 
    for(i=circArray.length; i>=0; i--){ //loop in reverse draw order 
     dx = mouseX - circArray[i].x; 
     dy = mouseY - circArray[i].y; 
     if (Math.sqrt((dx*dx) + (dy*dy)) < circArray[i].r) {   
      //we've hit an item 
      dragIdx = i; //store the item being dragged 
      dragOffsetX = dx; //store offsets so item doesn't 'jump' 
      dragOffsetY = dy; 
      canvas.addEventListener("mousemove",mousemove); //start dragging 
      canvas.addEventListener("mouseup",mouseup); 
      return; 
     } 
    } 
} 

function mousemove(e) { 
    //...calc coords 
    circArray[dragIdx].x = mouseX + dragOffsetX; //drag your item 
    circArray[dragIdx].y = mouseY + dragOffsetY; 
    //...repaint(); 
} 

function mouseup(e) { 
    dragIdx = -1; //reset for next mousedown 
    canvas.removeListener(.... //remove the move/up events when done 
} 

Mi js está oxidado por el momento, pero esto debería dar la idea. El dragOffsetX/Y se usa para evitar que el elemento salte al cursor al hacer clic. También podría simplemente almacenar la antigua coordenada del mouse y agregar un delta a su elemento.

Además, en lugar de almacenar un índice en su elemento de arrastre, puede almacenar una referencia o una serie de referencias para arrastrar varios elementos. Y en lugar de manipular directamente sus elementos, puede poner una interfaz mousedown/drag/up en ellos para que puedan manejarlo. Esto hará que sea más fácil mezclar otros tipos de artículos.

Otra cosa de la que no estoy seguro es cómo está calculando sus coordenadas. Hago algo diferente, pero es un código más antiguo y supongo que a tu manera también se mide. -t

+0

Estoy bastante seguro de que 'circArray [dragIdx] .x = mouseX + dragOffsetX;' en realidad debería ser 'circArray [dragIdx] .x = mouseX - dragOffsetX; '. Para que el dragOffset se resta de la ubicación del mouse. – JaAnTr