I've started a new project with Pixi JS. I've used this tutorial (along with a lot of stack overflow)
https://github.com/kittykatattack/learningPixi
and it's been a great site to get a better understanding of HTML5 development with pixi js framework. However, I ran into an issue with clicking an dragging sprites. The example the Pixi JS site
https://pixijs.io/examples/#/interaction/dragging.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | const app = new PIXI.Application({ backgroundColor: 0x1099bb }); document.body.appendChild(app.view); // create a texture from an image path const texture = PIXI.Texture.from('examples/assets/bunny.png'); // Scale mode for pixelation texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST; for (let i = 0; i < 10; i++) { createBunny( Math.floor(Math.random() * app.screen.width), Math.floor(Math.random() * app.screen.height), ); } function createBunny(x, y) { // create our little bunny friend.. const bunny = new PIXI.Sprite(texture); // enable the bunny to be interactive... this will allow it to respond to mouse and touch events bunny.interactive = true; // this button mode will mean the hand cursor appears when you roll over the bunny with your mouse bunny.buttonMode = true; // center the bunny's anchor point bunny.anchor.set(0.5); // make it a bit bigger, so it's easier to grab bunny.scale.set(3); // setup events for mouse + touch using // the pointer events bunny .on('pointerdown', onDragStart) .on('pointerup', onDragEnd) .on('pointerupoutside', onDragEnd) .on('pointermove', onDragMove); // For mouse-only events // .on('mousedown', onDragStart) // .on('mouseup', onDragEnd) // .on('mouseupoutside', onDragEnd) // .on('mousemove', onDragMove); // For touch-only events // .on('touchstart', onDragStart) // .on('touchend', onDragEnd) // .on('touchendoutside', onDragEnd) // .on('touchmove', onDragMove); // move the sprite to its designated position bunny.x = x; bunny.y = y; // add it to the stage app.stage.addChild(bunny); } function onDragStart(event) { // store a reference to the data // the reason for this is because of multitouch // we want to track the movement of this particular touch this.data = event.data; this.alpha = 0.5; this.dragging = true; } function onDragEnd() { this.alpha = 1; this.dragging = false; // set the interaction data to null this.data = null; } function onDragMove() { if (this.dragging) { const newPosition = this.data.getLocalPosition(this.parent); this.x = newPosition.x; this.y = newPosition.y; } } |
has bunny's that you can click on and drag. However, if you click on the lower right leg of the bunny and start to drag, the sprite jumps so that the center of the bunny is where the mouse is:
It seems trivial but when you are using larger sprites, it becomes borderline non-functional. Looking at the code you can see bunny.anchor.set(0.5) will move the sprite's anchor to the center instead of the top left. If you comment this out, you will see the the bunny jump more when you attempt to click and drag.
So how to fix this? So far I haven't been able to find a mouse location related to sprint you are clicking on. However, you can extract the mouse location for the app (screen area) and the sprite's location. From this, you can calculate an offset x and y coordinate when to initially mouseDown and drag. The offset helps update the anchor coordinate to prevent the jumping around of the sprite like so
Here is the updated code. Hope this helps someone!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | const app = new PIXI.Application({ backgroundColor: 0x1099bb }); document.body.appendChild(app.view); // create a texture from an image path const texture = PIXI.Texture.from('examples/assets/bunny.png'); // Scale mode for pixelation texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST; // Sprite drag offset let spriteMouseLocationOffsetX = 0; let spriteMouseLocationOffsetY = 0; for (let i = 0; i < 10; i++) { createBunny( Math.floor(Math.random() * app.screen.width), Math.floor(Math.random() * app.screen.height), ); } function createBunny(x, y) { // create our little bunny friend.. const bunny = new PIXI.Sprite(texture); // enable the bunny to be interactive... this will allow it to respond to mouse and touch events bunny.interactive = true; // this button mode will mean the hand cursor appears when you roll over the bunny with your mouse bunny.buttonMode = true; // center the bunny's anchor point bunny.anchor.set(0.5); // make it a bit bigger, so it's easier to grab bunny.scale.set(3); // setup events for mouse + touch using // the pointer events bunny .on('pointerdown', onDragStart) .on('pointerup', onDragEnd) .on('pointerupoutside', onDragEnd) .on('pointermove', onDragMove); //For mouse-only events // .on('mousedown', onDragStart) // .on('mouseup', onDragEnd) // .on('mouseupoutside', onDragEnd) // .on('mousemove', onDragMove); // For touch-only events // .on('touchstart', onDragStart) // .on('touchend', onDragEnd) // .on('touchendoutside', onDragEnd) // .on('touchmove', onDragMove); // move the sprite to its designated position bunny.x = x; bunny.y = y; // add it to the stage app.stage.addChild(bunny); } function onDragStart(event) { // store a reference to the data // the reason for this is because of multitouch // we want to track the movement of this particular touch this.data = event.data; this.alpha = 0.5; this.dragging = true; // get the mouse coursor location within the window const appCursorLocation = this.data.getLocalPosition(this.parent); // calculate the offset with the app cursor location - sprite location spriteMouseLocationOffsetX = appCursorLocation.x - this.x spriteMouseLocationOffsetY = appCursorLocation.y - this.y } function onDragEnd() { this.alpha = 1; this.dragging = false; // set the interaction data to null this.data = null; spriteMouseLocationOffsetX = 0; spriteMouseLocationOffsetY = 0; } function onDragMove() { if (this.dragging) { const newPosition = this.data.getLocalPosition(this.parent); // adjust the sprite prosition using the offset this.x = newPosition.x - spriteMouseLocationOffsetX; this.y = newPosition.y - spriteMouseLocationOffsetY; } } |