How to calculate mouse relative offset to transformed parent - javascript

How can I calculate offsetX and offsetY of the mouse cursor, relative to an element being transformed, even though the mouse is not moving?
https://jsfiddle.net/kevin_dorion/usrLd1x3/34/
// this is the value I need to update, even when the mouse is not moving
offsetEl.innerHTML = `x: ${evt.offsetX} y: ${evt.offsetY}`;
As you can see, on mousemove, I get the offsetX and offsetY values, which are exactly what I need. But I also need to be aware of these values changing when the mouse is not moving.
requestAnimationFrame(animate);
// how do I manually calculate offsetX and offsetY of the mouse cursor relative to the "el" element when the mouse is not moving?
I was thinking of keeping the last mouse event, use the pageX/pageY to position an element, then calculate its offset, but I can't get it working properly.
Thank you!
EDIT: I was thinking of storing the last known matrix / mouse coordinates combinaison, use the current matrix and make some interpolation, but I can't get it right either...

Related

How to get distanse from click initial coordinates (mousedown) to last mouse position (mouseup)?

Here jsfiddle I have behaviour with mouse
Click (this will show you initial coordinates)
Move mouse whereever you want
On mouseup I want get a distance in px of Y and X from initial position
Now if you make circles around your initial mouse position you can get 100000+ distance. Because it just infinitely added.
Here jsfiddle you can see great example of needed result. BUT, I need to get separate Y and X, and only on mouseup

How to re-position element on 'enddrag'?

I was wondering how you would be able to use the 'enddrop' event listener to change the position of an element.
I tried using this:
document.addEventListener('dragend', e => {
e.target.style.left = e.clientX;
e.target.style.top = e.clientY;
});
This works, but it's looks un-natural because the coordinates of the upper-left of the element are changed to the mouse position. So, if the user drags the element by the upper-left point it will work perfectly, but if you drag anywhere else on the element, it gives it a snappy effect because the upper-left corner will snap to the mouse's position.
Thanks!
I recently solved a similar problem:
follow the link: Prevent drop event when it's already have child element ? Drag and Drop
at the moment you start drag(dragstart) you calculate the top and left offset based on the element and mouse position
and at the end drag(dragend) event you use this offset to adapt as needed.
let offset = [0, 0] // initial state offset x, y
function dragStart(ev) {
// your code..
offsetX = ev.target.offsetLeft - ev.clientX
ev.target.offsetLeft - ev.clientX,
ev.target.offsetTop - ev.clientY
]
}
Any doubt put the code that I can help you.
Hope this helps.

Tracking relative mouse position without a mousemove event

I need to track mouse position relative to a <canvas> element in my app. Currently, I have a mousemove event listener attached to the <canvas> that updates my mouse position whenever it fires, using offsetX/offsetY when available, or layerX/layerY when the offsetX/Y is not available. Using offsetX/Y or layerX/Y gives me mouse coordinates relative to my <canvas>, which is exactly what I want. As my app works its magic, various CSS 3d transformations get applied to the <canvas>, and even when <canvas> is very transformed, offsetX/Y still gives me accurate coordinates within the <canvas>'s local, transformed coordinate-space.
That's kind of confusing, so I'll try stating an example. If my <canvas> is 100px in both width and height, and is located at (0,0) relative to the browser viewport, and I click at (50,50) (in viewport coords), that corresponds to (50,50) in my <canvas>, and 50 is the value that is (correctly) returned via offsetX and offsetY. If I then apply transform: translate3d(20px,20px,0px) to my <canvas> and click at (50,50) (in viewport coords), since my canvas has been shifted 20px down and 20px to the right, that actually corresponds to (30,30) relative to the <canvas>, and 30 is the value that is (correctly) returned via offsetX and offsetY.
The problem I'm facing is what to do when the user is not physically moving the mouse, yet the <canvas> is being transformed. I'm only updating the position of the mouse on mousemove events, so what do I do when there is no mousemove?
For example. My mouse is positioned at (50,50) and no transformations are applied to the <canvas>. My this.mouseX and this.mouseY are both equal to 50; they were saved at the final mousemove event when I moved the mouse to (50,50). Without moving the mouse at all, I apply the above transformation (transform: translate3d(20px,20px,0px)) to my <canvas>. Now, I need this.mouseX and this.mouseY to each be equal to 30, as that is my mouse's new position relative to the current transformation of <canvas>. But this.mouseX and this.mouseY are still equal to 50. Since I never moved the mouse, there was no mousemove event fired, and those saved coords never got updated.
How can I deal with this? I thought about creating a new jQuery event, manually assigning some properties (pageX and pageY?) based on my old/previous mouse position, and then triggering that event, but I don't think that's going to cause the browser to recalculate the offsetX and offsetY properties. I've also been thinking about taking the known old/previous mouse position and multiplying it by my transformation matrix, but that's going to get real complicated since my mouse coordinates are in 2d-space, but the transformations I'm applying to <canvas> are all 3d transformations.
I guess really, what I want to do is take my known 2d page position and raycast it into the 3d space and find out where I'm hitting the transformed <canvas>, all in javascript (jQuery is available).
Is this possible? Does this even make sense?
Works in all browsers
var mouseX=0;
var mouseY=0;
var canvas = document.querySelector('#canvas');
var rect = canvas.getBoundingClientRect();
document.onmousemove = function(e) {
mouseX=e.clientX-rect.left;
mouseY=e.clientY-rect.top;
};
function updateCoords() {
mouseX=e.clientX-mouseX;
mouseY=e.clientY-mouseY;
setTimeout(updatecoords,10);
}
Now we can call updateCoords() function once to repeatedly check for new position.
updateCoords();
You can add your code inside the updateCoords() function and it will be executed each 10 milliseconds
Concept: mouseX and mouseY variables get updated on mousemove event, and also get updated when there is any change in the canvas position.
It looks like you want to refresh your mouseposition-values even if you don't move your mouse. You should try something like this:
var event = '';
var counter = 1;
$(function(e){
event = e;
window.setInterval(refresh, 10);
});
$(document).mousemove(function(e){
event = e;
refresh;
});
function refresh(){
counter++;
$('#mousepos').val("event.pageX: " + event.pageX + ", event.pageY: " + event.pageY + ", counter: " + counter)
}
The counter is just for visualisation of the refresh. You can set the interval to everything you want (10 = 10ms = 0.01s) Just move everything from your .mousemove() event into this refresh() function and call it properly and your mouse position should update even if you don't move your mouse.
Look at this fiddle for a life example: http://jsfiddle.net/82cmxw8L/1
EDIT:
Because my fiddle didn't work for the asker, i updated it: http://jsfiddle.net/82cmxw8L/8/
New is, that the mouseposition is now set every 0.1 Second, no matter what, rather than being updated only when the mouse moves.

jQuery making element move with mouse

So I can make an element move with the mouse, however the problem is the offset is calculated from the top left corner of the element and doesn't take into account the mouse's position within the element causing the object to leap towards the mouse and preventing you from dragging it upwards or left.
So I came up with this function:
handle.on("mousemove", function(e) {
if (state.dragging) {
var paneOffset = pane.offset();
var mouseOffset = {
'top': e.pageY - paneOffset.top,
'left': e.pageX - paneOffset.left
}
pane.offset({
top: e.pageY - mouseOffset.top,
left: e.pageX - mouseOffset.left
});
}
});
Example: http://jsfiddle.net/SEKxc/
The problem with this is it stops the element from moving as it always calculates the element's same exact offset. How would I make the element follow the mouse but relative to the mouse's position with the object.
I am aware of jQueryUI having this functionality built-in but don't want to use that.
You could calculate the initial mouseoffset on dragstart and hence use it as a global variable from within the mousemove handler. Since the dragstart starts before mouse move i dont see a problem.
Update: you need to store both the objects initial offset and the mouses initial offset and calculate the relative offset of the mouse compared to the original on mouseMove then apply the same transformation to the element.
Store the distance between the mouse position and the element top left corner when you start dragging. Then you just subtract those from the mouse position to calculate the element position when the mouse moves.

Use CSS3 transforms to center viewport around mouse click position

I would appreciate your help with the following issue: I want to use CSS3 transforms in order to center the view-port of the browser around the position of a mouse click.
Please have a look at my commented example at http://jsfiddle.net/XjpdU/.
The problem that I have is that the translation works fine only on the first click. After the first click the distance between the center of the view-port and the mouse click position seems to be computed correctly, but the translation seems to jump just anywhere.
I have tried to explicitly set 'transform-origin' (-webkit-translate-origin in my example) to the position of the last click (i.e., the current center of the view-port) but it seems that with 'translate' the 'transform-origin' directive simply gets ignored.
Thanks for helping out!y
Yep, transform-origin has no effect on the translation. It works like this:
Start with the identity matrix.
Translate by the computed X, Y and Z values of ‘transform-origin’
Multiply by each of the transform functions in ‘transform’ property in turn
Translate by the negated computed X, Y and Z values of ‘transform-origin’
http://www.w3.org/TR/css3-transforms/#transform-rendering
What you could do is remember the translate, and add the newly calculated one to it, this will cause a relative translation starting from the previous point.
x = prevX = prevX + newX
y = prevY = prevY + newY
http://jsfiddle.net/XjpdU/1/

Categories

Resources