Jump to content

Drag and drop without frame lag


westy
 Share

Recommended Posts

I've been trying to implement drag and drop for some of the sprites in my project.

I've managed to get it working to some extent using code that I found in a tutorial/example somewhere - the exact source escapes me, apologies. (It's in typescript but should be pretty much recognisable as js)

constructor() {
	this.on("mousedown", this.startDrag);
	this.on("mouseup", this.endDrag);
	this.on("mouseupoutside", this.endDrag);
	this.on("mousemove", this.onDrag);
}

private startDrag(e: PIXI.interaction.InteractionEvent) {
	this.dragging = true;
	e.data.getLocalPosition(this.parent, this.lastDragPos);
}

private endDrag() {
	this.dragging = false;
}

private onDrag(e: PIXI.interaction.InteractionEvent) {
	if (this.dragging) {
		e.data.getLocalPosition(this.parent, this.dragPos);
		this.position.x += (this.dragPos.x - this.lastDragPos.x);
		this.position.y += (this.dragPos.y - this.lastDragPos.y);
		e.data.getLocalPosition(this.parent, this.lastDragPos);
	}
}

However this approach seems to have a number of problems.

  • The deal breaker here is that the object is always one (or maybe even more??) frames behind the mouse. To me this is unacceptable and leads to all kinds of nonsense like needing the mouseupoutside event to work properly.
  • There are a whole lot of edge cases, like letting go of the dragged object when it's over another draggable object causes problems, etc, etc...

I'm guessing that the first problem is caused because this is using the event system and isn't coupled to the render loop. 

Is there a better way to do drag and drop in PIXI? Also open to any hints on mouse interaction in general, the documentation hasn't been hugely helpful to me (i.e. what's the purpose of the interactionManager?)

Thanks!

Link to comment
Share on other sites

1. Your guess is right. You can try to look in the code (WebGLRenderer.renderWebGL) , and actually call updateTransform() and then interaction before the rendering itself. Also you have to handle events not when they appear but between updateTransform() and render()

2. There is still no bubbling of events, so yes, if container and element are both interactive, its a problem for drag. (https://github.com/pixijs/pixi.js/pull/2358/ is solution, still not merged)

3. Like you said,  if some object appears above draggable, then it is a problem too. You can move temporarily move object to first position in children array.

We are waiting for a messiah that will solve all that and make Pull Request for all these problems. I solved it all with hacks in my games, but i dont have generalized solution for you :(

Any way, you have to clone github repo, you wont find all these answers in docs.

If you really want to fix all these things, I can help, because I'll need them all too.

Link to comment
Share on other sites

I've actually generalized the drag and drop code and written it up in an article at codeproject:
http://www.codeproject.com/Articles/1096331/Algorithm-Calc-Convex-Hull-Draw-HTML-Canvas-Part

It's part of another series of articles I've written, but you'll see the drag and drop functionality is separated out so you can easily use the code.

Also you can see the animated gif of the simplified code working : 

movePoints.gif

Hope this helps.  

Link to comment
Share on other sites

Hi radevus,

You can do something like this. (I made this for for an editor Im working on)

http://designer.tankwars.io/scripts/global/mouseevents.js

it covers: click, rightclick, middleclick, down, rightdown, middledown, up, rightup, middleup, drag, dragend, dragstart, rightdrag, rightdragend, rightdragstart, middledrag, middledragend, middledragstart, over and out.

You need to change the "scene.mousePos" parts to another representation of mouseposition. (maybe "renderer.plugins.interaction.mouse.global")

And for "_lastPosition: new Point()" you would need to use "new PIXI.Point()" (I'm using my own point class).

 

Use it like this

var Button = PIXI.Sprite.fromImage('...');
MouseEvents.init(Button);

Button.mouse.click(function() {
    //...
});


or..

var Box = PIXI.Sprite.fromImage('...');
MouseEvents.init(Box);

Box.mouse.dragstart(function() {
    //...
});

Box.mouse.drag(function() {
    //...
});

Box.mouse.dragend(function() {
    //...
});

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...