Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sprite snaps to mouse at sprite anchor position on mousemove #180

Closed
kva1966 opened this issue Jun 23, 2013 · 5 comments
Closed

Sprite snaps to mouse at sprite anchor position on mousemove #180

kva1966 opened this issue Jun 23, 2013 · 5 comments

Comments

@kva1966
Copy link

kva1966 commented Jun 23, 2013

  1. When dragging (mousemove), regardless of where on the sprite the mouse is placed, the sprite repositions itself such that the mouse pointer is now at the sprite's anchor position.
  2. For larger sprites, this shift is fairly jarring.
  3. It'd be nice to not require the mouse pointer to be at the anchor position. Internally, the anchor position must be maintained for calculations, etc. irrespective of mouse position on the sprite.
  4. Sample code and image attached. Notes on reproduction:
    • Code adapted and simplified from the dragging example in pixi.js (Example 8).
    • Download the image and rename to "aboriginal-bunny.png" as referenced in the code.
    • The bunny anchor point is set to 0.1, 0.1
    • Place the mouse cursor somewhere close to the bottom of the sprite, essentially anywhere far from the anchor point
    • On mousedown, the sprite's alpha changes, but everything else is the same, so the problem does not appear to be on mousedown.
    • Next, drag -- begin moving with mouse button down -- just slightly
    • Note the sudden shift of the sprite so the mouse is on its anchor point.
    • Henceforth, dragging is maintained with the mouse at this anchor.
<!DOCTYPE HTML>
<html>
<head>
    <!-- Shamelessly adapted from pixi.js Example 8 - Dragging -->
    <title>Sprite to Mouse Snapping issue</title>
    <script src="pixi.js"></script>
</head>
<body>
    <script>

    var stage = new PIXI.Stage(0x97c56e, true);
    var renderer = PIXI.autoDetectRenderer(window.innerWidth, window.innerHeight, null);

    // add the renderer view element to the DOM
    document.body.appendChild(renderer.view);
    renderer.view.style.position = "absolute";
    renderer.view.style.top = "0px";
    renderer.view.style.left = "0px";
    requestAnimFrame( animate );

    // create a texture from an image path
    var texture = PIXI.Texture.fromImage("aboriginal-bunny.png");

    createAboriginalBunny(100, 100);

    function createAboriginalBunny(x, y)
    {
        var bunny = new PIXI.Sprite(texture);
        bunny.setInteractive(true);

        // leaving anchor point at 10% to illustrate the problem clearer
        bunny.anchor.x = 0.1;
        bunny.anchor.y = 0.1;

        /*
         * Set-up dragging
         */     
        bunny.mousedown = bunny.touchstart = function(data)
        {
            this.data = data;
            this.alpha = 0.5;
            this.dragging = true;
        };

        bunny.mouseup = bunny.mouseupoutside = bunny.touchend = bunny.touchendoutside = function(data)
        {
            this.alpha = 1
            this.dragging = false;
            // set the interaction data to null
            this.data = null;
        };

        bunny.mousemove = bunny.touchmove = function(data)
        {
            if(this.dragging)
            {
                // need to get parent coords..
                var newPosition = this.data.getLocalPosition(this.parent);
                this.position.x = newPosition.x;
                this.position.y = newPosition.y;
            }
        }

        // move the sprite to initial pos
        bunny.position.x = x;
        bunny.position.y = y;

        stage.addChild(bunny);
    }

    function animate() {
        requestAnimFrame( animate );
        renderer.render(stage);
    }

    </script>

    </body>
</html>

aboriginal-bunny

@englercj
Copy link
Member

First of all, thank you for the detailed bug report and the sample code, it helps a lot when we are given so much information!

Unfortunately, this is not a bug. This issue is caused by you setting the position of the sprite to the position of the mouse each mousemove (most likely because that is what the example does). Really, what should happen is you should update your sprite by the delta of the mouse movement. Try something like this:

        /*
         * Set-up dragging
         */     
        bunny.mousedown = bunny.touchstart = function(data)
        {
            this.data = data;
            this.alpha = 0.5;
            this.dragging = this.data.getLocalPosition(this.parent);;
        };

        bunny.mouseup = bunny.mouseupoutside = bunny.touchend = bunny.touchendoutside = function(data)
        {
            this.alpha = 1
            this.dragging = false;
            // set the interaction data to null
            this.data = null;
        };

        bunny.mousemove = bunny.touchmove = function(data)
        {
            if(this.dragging)
            {
                // need to get parent coords..
                var newPosition = this.data.getLocalPosition(this.parent);
                this.position.x += (newPosition.x - this.dragging.x);
                this.position.y += (newPosition.y - this.dragging.y);
                this.dragging = newPosition;
            }
        }

The important bits are on mousedown I store the location of the mouse, then on mousemove I update my sprite position by how much the mouse has moved (not set it to the new position), then I update the stored mouse position for the next time. I hope this helps!

@kva1966
Copy link
Author

kva1966 commented Jun 23, 2013

Hello,

This resolves my issue, and is much clearer to understand, thanks. And yes, my code is based on how the example works, so would be good if the example could be updated -- I recall having trouble understanding how it worked, guess it did not fully work. :P

A related question, is there strictly a need to set interaction data to null on mouseup?

I'm also still unclear when getLocalPosition is required, vs. just the current position.

PS. no worries re: bug report detail, least I could do. Thanks for providing the library. :)

@englercj
Copy link
Member

The reason for getLocalPosition is to transform the absolute coords of the mouse event, into local relative coords that DisplayObjects use. Each DisplayObject's position is relative to its parent, so we take the absolute mouse coords and transform them to be relative to the parent with this.data.getLocalPosition(this.parent).

It is isn't particularly necessary to set this.data = null on mouseup. Really you should be able to just use the data param to each function, and not use this.data at all.

@kva1966
Copy link
Author

kva1966 commented Jun 23, 2013

Thanks again for your help; pretty new to graphics libs, so getting to terms with various implementation choices. Appreciate the pixi devs taking the time to answer my questions in a timely manner.

@kva1966 kva1966 closed this as completed Jun 23, 2013
@lock
Copy link

lock bot commented Feb 27, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked and limited conversation to collaborators Feb 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants