Move mesh towards pointer as long as it's pressed

Hello! I’m trying to come up with a pointer control where pressing & holding would move a character model towards the pointer position while the pointer is pressed. I’ve came up with most of the code for it, however, JS pointerdown event is not like keydown that keeps being fired as long as it’s pressed. This causes a behavior where the raycaster won’t be updated if pointer is not moving. Any ideas to circumvent this?

Code

Reproduction

I’d do this in 4 steps:

  • when pressing the pointer remember that it is pressed and store the coordinates as a target
  • when the pointer is released, forget that it is pressed
  • when the pointer is moving while it is pressed, update the target
  • in the main animation loop, while the pointer is pressed, move the object towards the target

Live demo (you may move the pointer while it is pressed):

https://codepen.io/boytchev/full/oNRpreb

Thanks for the reply! I’m doing the same thing as you suggested. The problem is, however, that the camera is always following the character, so I also wanted the mouse down position to be updated.

Example:


(Note: the red sign is shown as long as the user is clicking)

The behavior I want here is to keep updating the cursor position as long as the mouse button is being pressed. Basically the distance between the cursor position and the character itself won’t ever change, if that makes sense

What is preventing you from updating the position in the animation loop?

You can use raycasting (against the ground), or if you are a Math-aficionado, you may calculate the position (that would be faster than raycasting)

PS. None of the videos that you posted can be played on my machine

1 Like

Ah, that explains it! I’ve solved it the way you explained! Thanks a lot, dude!

I’ve updated the event listeners to be:

window.addEventListener('pointerdown', (event) => {
      this.pressed = true;
      this.updatePosition(event);
    });
    window.addEventListener('pointerup', () => {
      this.pressed = false;
      if (this.animationFrameID) cancelAnimationFrame(this.animationFrameID);
    });

    window.addEventListener('pointermove', (event) => {
      if (this.pressed) this.updatePosition(event);
    });

And exported a update method:

update = () => {
    this.raycaster.setFromCamera(this.position, this.camera);
  };

And called it at tick:

const tick = () => {
  window.requestAnimationFrame(tick);
  const delta = sceneManager.update();
  mouse.update();
  controls.update(delta);
};

It works flawlessly now!

(About the videos: that’s probably because I’ve uploaded WEBMs)

2 Likes