0

I'm trying to make an element moves when the mouse moves in a random 340° direction excluding the 20° of the cursor so the element won't move to the cursor but when I translate It always goes back to the origin place as if there were no translating. here's the code:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>SVG</title>
</head>

<body>
    <svg id="m" width="40" height="40">
        <circle cx="20" cy="20" r="20" fill="red" stroke="red" stroke-width="1"/>
    </svg>
    
    <script>
let m = document.getElementById("m");
let angle = Math.floor(Math.random() * 340) * Math.PI / 180;
var timestamp, lastMouseX, lastMouseY = null;

let setCursorPosition = function(e) {

  //mousespeed
  if (timestamp === null) {
        timestamp = Date.now();
        lastMouseX = e.screenX;
        lastMouseY = e.screenY;
        return;
    }
    var now = Date.now();
    var dt =  now - timestamp;
    var dx = e.screenX - lastMouseX;
    var dy = e.screenY - lastMouseY;
    var speedX = Math.round(dx / dt * 100);
    var speedY = Math.round(dy / dt * 100);
    
    timestamp = now;
    lastMouseX = e.screenX;
    lastMouseY = e.screenY;
  //
  
  m.style.transform = "translate(" + Math.cos(angle)*speedX + "px," + Math.sin(angle)*speedY + "px)"; 
};

document.addEventListener("mousemove", e => setCursorPosition(e));
    </script> 
</body>

</html>

thanks

also tell me if the implementation of the direction of the element is just like I wanted or no, I have a feeling that it's wrong

Mhmd Admn
  • 357
  • 3
  • 10

1 Answers1

1

I'm not entirely sure what you're going for here, but I played around with you code and I think I got it to behave how you want it to. The first thing I noticed (very minor), was that this line:

var timestamp, lastMouseX, lastMouseY = null;

should be:

var timestamp = null, lastMouseX = null, lastMouseY = null;

Otherwise you are not actually setting timestamp and lastMouseX initially.

More importantly, the reason your element continues to return to its origin is that it's getting very small mouse inputs as you decelerate your mouse so speedX and speedY are set to low values at the end of each mouse move.

To fix this I added a this line right before your transform command:

if (Math.abs(speedX) < 40 && Math.abs(speedY) < 40) return;

Also to make the movement a little smoother I also added a throttle to your event listener so that setCursorPosition isn't called quite so often (reduces jittery movement), and I added a transition in the styles.

function throttle(func, interval) {
    var lastCall = 0;
    return function() {
        let curTime = Date.now();
        if (lastCall + interval < curTime) {
            lastCall = curTime;
            return func.apply(this, arguments);
        }
    };
}   
      
document.addEventListener("mousemove", throttle(setCursorPosition, 20));
/* ^ replace original document.addEventListener() with this */
#m {
  transition: transform 140ms;
  margin: 200px; //just so I could always see it on the screen
}

The numbers I used for the min speed, throttle, and transition were purely experimental so feel free to play around with them to your liking.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Bdeering
  • 338
  • 3
  • 14
  • thanks a lot for taking your time to do this, actually I moved from this code because someone told me I was doing it wrong now I am playing with this one https://pastebin.com/T8WhBZMA but the circle always stays in its place. thanks anyway – Mhmd Admn Mar 09 '21 at 18:47
  • and thanks for your suggestions, I'm using that throttle – Mhmd Admn Mar 09 '21 at 18:51