最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - cleanest Drag and Drop code in Javascript Canvas - Stack Overflow

programmeradmin3浏览0评论

I'm looking for the fastest and lightest way to drag and drop shapes and sprites on a JS Canvas for game-development purposes.

I've started by doing distance checks using the current mouse position and the origins of circles. It works, but when they overlap we have problems and I don't know how well this will work when testing for multiple sprites and other shapes yet on each 'frame'.

Any ments or pointers to better methods are appreciated!

I'd rather not use a library like jQuery since I'm going for pure speed and lightness and of course to learn the actual methods! Here's where I'm at:

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

I'm looking for the fastest and lightest way to drag and drop shapes and sprites on a JS Canvas for game-development purposes.

I've started by doing distance checks using the current mouse position and the origins of circles. It works, but when they overlap we have problems and I don't know how well this will work when testing for multiple sprites and other shapes yet on each 'frame'.

Any ments or pointers to better methods are appreciated!

I'd rather not use a library like jQuery since I'm going for pure speed and lightness and of course to learn the actual methods! Here's where I'm at:

//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;
}
Share Improve this question edited Dec 16, 2011 at 1:14 Jonas 129k102 gold badges327 silver badges405 bronze badges asked Dec 16, 2011 at 0:26 VerneVerne 711 gold badge1 silver badge2 bronze badges 2
  • 1 You're thinking of jQuery UI draggables (jqueryui./demos/draggable). Even if you don't go with jQuery I would highly advise checking out an unminified version and see what they do. The developers have definitely thought through some of these performance issues. Because of the liberal license you can likely cut out a small piece of the codebase. – buley Commented Dec 16, 2011 at 0:35
  • 1 You may want to look at fabric.js. Here's a demo: kangax.github./fabric.js/stickman – Jim Schubert Commented Dec 16, 2011 at 1:18
Add a ment  | 

1 Answer 1

Reset to default 3

Here's the setup I've used for dragging a single item. I can't tell if you want to drag multiple things or not, that'd be a slight modification.

In words: in mousedown search for a hit object in the reserved order you drew the objects (so the topmost item gets hit first), store this hit item, then mousedrag is simply piping the coords/delta to that item.

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

My js is rusty at the moment but this should give the idea. The dragOffsetX/Y is used to keep the item from jumping to the cursor when clicked. You could also just store the old mouse coordinate and add a delta to your item.

Also, instead of storing an index to your drag item you could store a reference to it, or maybe an array of references to drag multiple items. And instead of directly manipulating your items you could put a mousedown/drag/up interface on them to let them handle it. This'll make it easier to mix in other types of items.

Another thing I'm not sure about is how you're calculating your coordinates. I do something different but it's older code and I'm guessing your way measures just as well. -t

发布评论

评论列表(0)

  1. 暂无评论