2011-12-16 4 views
7

Szukam najszybszego i najlżejszego sposobu przeciągania i upuszczania kształtów i ikonek na JS Canvas w celach związanych z tworzeniem gier.najczystszy kod Przeciągnij i upuść w Javascript Canvas

Zacząłem od sprawdzania odległości za pomocą aktualnej pozycji myszy i początków kół. Działa, ale kiedy się nakładają, mamy problemy i nie wiem, jak dobrze to będzie działać podczas testowania wielu duszków i innych kształtów jeszcze na każdej "ramce".

Wszelkie uwagi i wskazówki dotyczące lepszych metod są mile widziane!

Wolałbym nie korzystać z biblioteki takiej jak jQuery, ponieważ wybieram czystą szybkość i lekkość i oczywiście poznaję rzeczywiste metody! Oto gdzie jestem:

//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

Myślisz o draggables UI jQuery (http://jqueryui.com/demos/draggable/). Nawet jeśli nie skorzystasz z jQuery, bardzo polecam sprawdzenie niezminijalowanej wersji i zobaczenie, co robią. Twórcy zdecydowanie przemyśleli niektóre z tych problemów z wydajnością. Ze względu na liberalną licencję prawdopodobnie można wyciąć mały fragment kodu. – buley

+1

Możesz zajrzeć do [fabric.js] (https://github.com/kangax/fabric.js). Oto wersja demonstracyjna: http://kangax.github.com/fabric.js/stickman/ –

Odpowiedz

3

Oto konfiguracja, której użyłem do przeciągnięcia pojedynczego przedmiotu. Nie mogę powiedzieć, czy chcesz przeciągnąć wiele rzeczy, czy nie, to byłaby drobna modyfikacja.

W słowach: w wyszukiwaniu szukanego obiektu w zarezerwowanej kolejności narysowałeś obiekty (aby najpierw trafił się najwyższy przedmiot), zapisz przedmiot trafienia, następnie mousedrag po prostu wypuszcza do niego element/współrzędne.

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

Mój js jest zardzewiały w tej chwili, ale to powinno dać pomysł. DragOffsetX/Y służy do tego, aby element nie przeskoczył do kursora po kliknięciu. Możesz również po prostu zapisać poprzednią współrzędną myszy i dodać deltę do swojego przedmiotu.

Ponadto, zamiast zapisywania indeksu do elementu przeciągania, można zapisać odniesienie do niego lub tablicę odniesień do przeciągania wielu elementów. Zamiast bezpośrednio manipulować twoimi przedmiotami, możesz umieścić na nich interfejs mousedown/drag/up, aby pozwolić im się nim posługiwać. Ułatwi to miksowanie w innych rodzajach przedmiotów.

Inną rzeczą, której nie jestem pewien, jest sposób obliczania współrzędnych. Zrobiłem coś innego, ale jest to starszy kod i domyślam się, że tak samo. -t

+0

Jestem prawie pewny, że 'circArray [dragIdx] .x = mouseX + dragOffsetX;' powinien w rzeczywistości być 'circArray [dragIdx] .x = mouseX - dragOffsetX; '. Tak, że dragOffset jest odejmowany od lokalizacji myszy. – JaAnTr