Pixi.js: Sprite se ajusta ao mouse na posição de âncora do sprite no movimento do mouse

Criado em 23 jun. 2013  ·  5Comentários  ·  Fonte: pixijs/pixi.js

  1. Ao arrastar (mousemove), independentemente de onde o sprite o mouse está posicionado, o sprite se reposiciona de forma que o ponteiro do mouse esteja agora na posição de âncora do sprite.
  2. Para sprites maiores, essa mudança é bastante chocante.
  3. Seria bom não exigir que o ponteiro do mouse esteja na posição de âncora. Internamente, a posição da âncora deve ser mantida para cálculos, etc. independente da posição do mouse no sprite.
  4. Código de amostra e imagem em anexo. Notas sobre a reprodução:

    • Código adaptado e simplificado do exemplo de arrastar em pixi.js (Exemplo 8).

    • Baixe a imagem e renomeie para "aboriginal-bunny.png" conforme mencionado no código.

    • O ponto de ancoragem do coelho é definido como 0,1, 0,1

    • Coloque o cursor do mouse em algum lugar próximo à parte inferior do sprite, essencialmente em qualquer lugar longe do ponto de ancoragem

    • No mousedown, o alfa do sprite muda, mas todo o resto é o mesmo, então o problema não parece estar no mousedown.

    • Em seguida, arraste - comece a mover com o botão do mouse para baixo - apenas ligeiramente

    • Observe a mudança repentina do sprite para que o mouse fique em seu ponto de ancoragem.

    • Doravante, o arrastar é mantido com o mouse nesta âncora.

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

Comentários muito úteis

Em primeiro lugar, obrigado pelo relatório de bug detalhado e pelo código de exemplo, ajuda muito quando recebemos tantas informações!

Infelizmente, isso não é um bug. Esse problema é causado por você definir a posição do sprite para a posição do mouse a cada movimento do mouse (provavelmente porque é isso que o exemplo faz). Realmente, o que deveria acontecer é que você deveria atualizar seu sprite pelo delta do movimento do mouse. Experimente algo assim:

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

Os bits importantes estão em mousedown eu armazeno a localização do mouse, então em mousemove eu atualizo minha posição de sprite por quanto o mouse se moveu (não o defini para a nova posição), então Eu atualizo a posição do mouse armazenada para a próxima vez. Eu espero que isso ajude!

Todos 5 comentários

Em primeiro lugar, obrigado pelo relatório de bug detalhado e pelo código de exemplo, ajuda muito quando recebemos tantas informações!

Infelizmente, isso não é um bug. Esse problema é causado por você definir a posição do sprite para a posição do mouse a cada movimento do mouse (provavelmente porque é isso que o exemplo faz). Realmente, o que deveria acontecer é que você deveria atualizar seu sprite pelo delta do movimento do mouse. Experimente algo assim:

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

Os bits importantes estão em mousedown eu armazeno a localização do mouse, então em mousemove eu atualizo minha posição de sprite por quanto o mouse se moveu (não o defini para a nova posição), então Eu atualizo a posição do mouse armazenada para a próxima vez. Eu espero que isso ajude!

Olá,

Isso resolve meu problema e é muito mais claro de entender, obrigado. E sim, meu código é baseado em como o exemplo funciona, então seria bom se o exemplo pudesse ser atualizado - lembro-me de ter tido problemas para entender como funcionava, acho que não funcionou totalmente. : P

Uma questão relacionada, é estritamente necessário definir os dados de interação como nulos no mouseup?

Também não estou certo quando getLocalPosition é necessário, em comparação apenas com a posição atual.

PS. não se preocupe com relação aos detalhes do relatório de bug, pelo menos eu poderia fazer. Obrigado por fornecer a biblioteca. :)

A razão para getLocalPosition é transformar as coordenadas absolutas do evento do mouse em coordenadas locais relativas que DisplayObjects usa. Cada posição de DisplayObject é relativa a seu pai, então pegamos as coordenadas absolutas do mouse e as transformamos para serem relativas ao pai com this.data.getLocalPosition(this.parent) .

Não é particularmente necessário definir this.data = null no mouseup. Na verdade, você deve ser capaz de usar apenas o parâmetro data para cada função, e não usar this.data alguma.

Obrigado novamente por sua ajuda; muito novo para bibliotecas gráficas, portanto, chegando a um acordo com várias opções de implementação. Agradeço os pixi devs por dedicarem seu tempo para responder às minhas perguntas em tempo hábil.

Este tópico foi bloqueado automaticamente, pois não houve nenhuma atividade recente depois que ele foi fechado. Abra um novo problema para bugs relacionados.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

zcr1 picture zcr1  ·  3Comentários

SebastienFPRousseau picture SebastienFPRousseau  ·  3Comentários

courtneyvigo picture courtneyvigo  ·  3Comentários

lucap86 picture lucap86  ·  3Comentários

Makio64 picture Makio64  ·  3Comentários