Drag objects in canvas
Asked Answered
G

5

16

Im looking for an easy to use method of assigning drag behavior to multiple objects (images, shapes etc) in canvas. Does anyone have a good way or know of any libraries for dragging objects around? Thanks

G answered 30/12, 2010 at 22:29 Comment(2)
what kinds of shapes do you want to drag, cirles, boxes, polygons? It works slightly differently for each.Bothwell
I haven't gotten around to trying shapes yet. Right now I'm just trying to figure out how to drag images that I've added to the canvas.G
B
19

Creating your own mouse events takes a little work - ideally you should either create or use some kind of mini-library. I'm thinking of creating something like this in the near future. Anyway, I created a drag and drop demo on jsFiddle showing how to drag images - you can view it here.

You can create draggable images like this:

var myImage = new DragImage(sourcePath, x, y);

Let me know if you have any questions about this. Hope it helps.

EDIT

There was a bug when dragging multiple images. Here is a new version.

Another thing you might want to check out is easeljs it sort of in the style of AS3... mouseEvents dragging etc...

Bothwell answered 31/12, 2010 at 15:50 Comment(6)
Tried your demo, this will work well for the time being. ThanksG
I noticed some strange behavior when you add more images. I suppose there needs to be a way to make sure its only dragging one image at a time.G
you could probably fix that with one variable... a boolean... let me take a look and I'll update my answerBothwell
no problem :) - I just updated it a bit further... it could still use some z-sorting. jsfiddle.net/Zevan/QZejF/5Bothwell
@Bothwell Any idea why this won't work in Firefox 3.6? I get an error in firebug pointing to line "c.drawImage(img, that.x, that.y);"G
yeah... i have a bad habbit of using offsetX/Y even though it barely works in any browser.... just change it to clientX and clientY and it should fix the problem : jsfiddle.net/QZejF/10 if you need to place the canvas somewhere other than the upper left hand corner of the stage - you need to do a little more code, I can post if you need - let me know.Bothwell
E
15

The HTML Canvas—unlike SVG or HTML—uses a non-retained (or immediate) graphics API. This means that when you draw something (like an image) to the canvas no knowledge of that thing remains. The only thing left is pixels on the canvas, blended with all the previous pixels. You can't really drag a subset of pixels; for one thing, the pixels that were 'under' them are gone. What you would have to do is:

  1. Track the mousedown event and see if it's in the 'right' location for dragging. (You'll have to keep track of what images/objects are where and perform mouse hit detection.)
  2. As the user drags the mouse, redraw the entire canvas from scratch, drawing the image in a new location each time based on the offset between the current mouse location and the initial mousedown location.

Some alternatives that I might suggest:

  • SVG
  • Pure HTML
  • Multiple layered canvases, and drag one transparent canvas over another.

The HTML Canvas is good for a lot of things. User interaction with "elements" that appear to be distinct (but are not) is not one of those things.

Update: Here are some examples showing dragging on the canvas:

None of these have created a separate library for tracking your shapes for you, however.

Eversion answered 31/12, 2010 at 1:25 Comment(2)
I see. Thanks for the clarifications. My plan is to eventually turn my code into a simple game. I would like to keep using canvas because it sounds like canvas is going to be have more browser support in the future. For the time being I dont mind going through the steps you outlined above but ideally I would like to find a library that I can plug into my code which helps me handle mouse interaction with elements.G
@G - I agree with Phrogz. When I first heard about canvas, I though it was going to be like a flash surface that we could use without flash. However as he says, there is no heirachy of 'objects' on the canvas, just one big collection of pixels. Move one thing and you will need to clear the canvas and redraw everything.Knotting
S
4

KineticJS is one such Javascript Library that u can use exclusively for animations

Heres the Link html5canvastutorials

Sycophancy answered 21/5, 2012 at 6:20 Comment(0)
L
2

Canvas and jCanvas

You're definitely gonna want to check out jCanvas. It's a super clean wrapper for Canvas, which kicks open a lot of doors without adding code complexity. It makes things like this a breeze.

For example, here's a little sandbox of something close to what you're after, with dragging and redrawing built right in:

Drawing an Arrow Between Two Elements.

Drawing an arrow

I ventured down the road of doing everything with DIVs and jQuery but it always fell short on interactivity and quality.

Hope that helps others, like me.

JP

Larentia answered 10/6, 2015 at 19:41 Comment(4)
Drawing arrow between two elements seems to be broken?Madge
@Madge You're right. Seems like the link to the sandbox is no longer populating the code properly. I wished I had copied the code into the answer itself. Ah well, you definitely want to checkout jCanvas as a solution here and if anybody redoes the code for this example, please update this answer.Larentia
Have you tried Fabric.js ? How would you compare that to jCanvas?Madge
@Madge No I haven't. This answer was from 5 years ago so not sure if that was even around then. But we're still using jCanvas and it was excellent to work with.Larentia
N
1

As you create new objects whether they are windows, cards, shapes or images to be draggable, you can store them in an array of "objects currently not selected". When you click on them or select them or start dragging them you can remove them from the array of "objects not selected". This way you can control what can move in the event of a particular mousedown event or mousemove event by checking if it isn't selected. If it is selected it will not be in the "not selected" array and you can move the mouse pointer over other shapes while dragging shapes without them becoming dragged.

Creating arrays of objects you would like to drag also helps with hierarchy. Canvas draws the pixels belonging to the foremost object last. So if the objects are in an array you simply switch their instance as in element in the array say from objectArray[20] to objectArray[4] as you iterate through the array and draw the objects stored in the array elements you can change whether other objects are seen on top or behind other objects.

Nomenclator answered 19/1, 2016 at 22:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.