1

I'm working on a map feature which should allow the user to drag rotate the map with the mouse.

This is the code of my mousedown event:

rotate.addEventListener('mousemove', (e) => { const elem = e.target; if (mouseDown) { const boundingRect = elem.getBoundingClientRect(); const center_x = boundingRect.left + boundingRect.width / 2; const center_y = boundingRect.top + boundingRect.height / 2; const mouse_x = e.pageX; const mouse_y = e.pageY; const radians = Math.atan2(mouse_x - center_x, mouse_y - center_y); const degree = radians * (180 / Math.PI) * -1 + 90; rotate.style.transform = `rotate(${degree}deg)`; } }); 

And here is the fiddle of the example: https://jsfiddle.net/8uexv2cp/3/.

So as you can see, it's kind of working. The problem is that if you start dragging in the top left corner, the element spins around (after this has happened it seems to be working as it should). Ideally I'd want it to just start rotating from the point that i select with the mouse and not having it flick around at the start.

What am I missing here?

I'd be happy to hear your thoughts about this.

Thanks

2
  • You got me looking at a solution I wrote years ago for this problem in Java Swing. I think my solution seems likely to suffer the same problem that you are describing here (the solutions are strikingly similar): sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/ex/… Commented Nov 17, 2020 at 14:41
  • That's interesting. Did you find out how to fix this? Browsed through the code but I dont have any java experience :) Commented Nov 18, 2020 at 8:15

2 Answers 2

1

So here is my solution after some fiddling.

on dragging start I save to original rotation angle of the element. Check this link for how to parse it out. And I also store the original point, from which we are dragging. This will be useful to calculate the direction of the dragging, once we start moving.

let currentDegree: number = 0; let center: {x: number, y: number}; function rotationStart(event: MouseEvent) { currentDegree = getCurrentRotation(element); center = {x: event.pageX, y: event.pageY} } 

Now it is time to the magic for moving. I calculate the direction of the movement and store it in radians. This is handy since, the positive value means I have to increase the degrees (rotate clockwise) and negative value is for decreasing (rotating anticlockwise). I just simply apply the new degrees to the element and store the new center element to recalculate the vector next time.

function rotation(event: MouseEvent) { let radians = Math.atan2(event.pageX - center.x, event.pageY - center.y); if (radians > 0) { ++currentDegree; } else { --currentDegree; } el.style.transform = `rotate(${currentDegree}deg)`; center = {x: pageX, y: pageY}; } 

You can possibly control the speed of the rotation by not just doing ++currentDegree, but doing something like currentDegree = currentDegree+3

Seems to be working pretty well.

Sign up to request clarification or add additional context in comments.

Comments

0
rotate.addEventListener('mousemove', (e) => { const elem = e.target; if (mouseDown) { const boundingRect = elem.getBoundingClientRect(); const center_x = boundingRect.left + boundingRect.width / 2; const center_y = boundingRect.top + boundingRect.height / 2; const mouse_x = e.pageX; const mouse_y = e.pageY; const radians = Math.atan2(mouse_x - center_x, mouse_y - center_y); const degree = radians * (180 / Math.PI) * -1 + **90**; rotate.style.transform = `rotate(${degree}deg)`; } }); 

The Degree u have put "90" should be "45"

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.