Related
I want to make a little painting app using canvas. So I need to find the mouse's position on the canvas.
As I didn't find a jQuery-free answer that I could copy/paste, here's the solution I used:
document.getElementById('clickme').onclick = function(e) {
// e = Mouse click event.
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
console.log("Left? : " + x + " ; Top? : " + y + ".");
}
#clickme {
margin-top: 20px;
margin-left: 100px;
border: 1px solid black;
cursor: pointer;
}
<div id="clickme">Click Me -<br>
(this box has margin-left: 100px; margin-top: 20px;)</div>
JSFiddle of full example
For people using JQuery:
Sometimes, when you have nested elements, one of them with the event attached to it, it can be confusing to understand what your browser sees as the parent. Here, you can specify which parent.
You take the mouse position, and then subtract it from the parent element's offset position.
var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;
If you're trying to get the mouse position on a page inside a scrolling pane:
var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();
Or the position relative to the page:
var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Note the following performance optimisation:
var offset = $('#element').offset();
// Then refer to
var x = evt.pageX - offset.left;
In this way, JQuery does not have to look up #element for each line.
Update
There is a newer, JavaScript-only version in an answer by #anytimecoder -- see also browser support for getBoundingClientRect().
The following calculates the mouse position relation to the canvas element:
const example = document.getElementById('example');
example.onmousemove = function(e) {
const x = e.pageX - e.currentTarget.offsetLeft;
const y = e.pageY - e.currentTarget.offsetTop;
}
There is no answer in pure javascript that returns relative coordinates when the reference element is nested inside others which can be with absolute positioning. Here is a solution to this scenario:
function getRelativeCoordinates (event, referenceElement) {
const position = {
x: event.pageX,
y: event.pageY
};
const offset = {
left: referenceElement.offsetLeft,
top: referenceElement.offsetTop
};
let reference = referenceElement.offsetParent;
while(reference){
offset.left += reference.offsetLeft;
offset.top += reference.offsetTop;
reference = reference.offsetParent;
}
return {
x: position.x - offset.left,
y: position.y - offset.top,
};
}
I tried all these solutions and due to my special setup with a matrix transformed container (panzoom library) none worked. This returns the correct value, even if zoomed and paned:
mouseevent(e) {
const x = e.offsetX,
y = e.offsetY
}
But only if there are no child elements in the way. This can be circumvented by making them 'invisible' to the event, using CSS:
.child {
pointer-events: none;
}
A good write up of the difficulty of this problem can be found here: http://www.quirksmode.org/js/events_properties.html#position
Using the technique that is described there you can find the mouses position in the document. Then you just check to see if it is inside the bounding box of your element, which you can find by calling element.getBoundingClientRect() which will return an object with the following properties: { bottom, height, left, right, top, width }. From there it is trivial to figure out if the even happened inside your element or not.
I came across this question, but in order to make it work for my case (using dragover on a DOM-element (not being canvas in my case)), I found that you only have have to use offsetX and offsetY on the dragover-mouse event.
onDragOver(event){
var x = event.offsetX;
var y = event.offsetY;
}
If you want to get the layerX and layerY related to one element, maybe you could try:
let bbox_rect = document.getElementById("dom-ID").getBoundingClientRect()
let layerX = e.clientX-bbox_rect.left
let layerY = e.clientY-bbox_rect.top
I +1' Mark van Wyk's answer as it got me in the right direction, but didn't quite solve it for me. I still had an offset on painting in elements contained within another element.
FOllowing solved it for me:
x = e.pageX - this.offsetLeft - $(elem).offset().left;
y = e.pageY - this.offsetTop - $(elem).offset().top;
In other words - i simply stacked all the offsets from all elements nested
For those of you developing regular websites or PWAs (Progressive Web Apps) for mobile devices and/or laptops/monitors with touch screens, then you have landed here because you might be used to mouse events and are new to the sometimes painful experience of Touch events... yay!
There are just 3 rules:
Do as little as possible during mousemove or touchmove events.
Do as much as possible during mousedown or touchstart events.
Cancel propagation and prevent defaults for touch events to prevent mouse events from also firing on hybrid devices.
Needless to say, things are more complicated with touch events because there can be more than one and they're more flexible (complicated) than mouse events. I'm only going to cover a single touch here. Yes, I'm being lazy, but it's the most common type of touch, so there.
var posTop;
var posLeft;
function handleMouseDown(evt) {
var e = evt || window.event; // Because Firefox, etc.
posTop = e.target.offsetTop;
posLeft = e.target.offsetLeft;
e.target.style.background = "red";
// The statement above would be better handled by CSS
// but it's just an example of a generic visible indicator.
}
function handleMouseMove(evt) {
var e = evt || window.event;
var x = e.offsetX; // Wonderfully
var y = e.offsetY; // Simple!
e.target.innerHTML = "Mouse: " + x + ", " + y;
if (posTop)
e.target.innerHTML += "<br>" + (x + posLeft) + ", " + (y + posTop);
}
function handleMouseOut(evt) {
var e = evt || window.event;
e.target.innerHTML = "";
}
function handleMouseUp(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
}
function handleTouchStart(evt) {
var e = evt || window.event;
var rect = e.target.getBoundingClientRect();
posTop = rect.top;
posLeft = rect.left;
e.target.style.background = "green";
e.preventDefault(); // Unnecessary if using Vue.js
e.stopPropagation(); // Same deal here
}
function handleTouchMove(evt) {
var e = evt || window.event;
var pageX = e.touches[0].clientX; // Touches are page-relative
var pageY = e.touches[0].clientY; // not target-relative
var x = pageX - posLeft;
var y = pageY - posTop;
e.target.innerHTML = "Touch: " + x + ", " + y;
e.target.innerHTML += "<br>" + pageX + ", " + pageY;
e.preventDefault();
e.stopPropagation();
}
function handleTouchEnd(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
// Yes, I'm being lazy and doing the same as mouseout here
// but obviously you could do something different if needed.
e.preventDefault();
e.stopPropagation();
}
div {
background: yellow;
height: 100px;
left: 50px;
position: absolute;
top: 80px;
user-select: none; /* Disable text selection */
-ms-user-select: none;
width: 100px;
}
<div
onmousedown="handleMouseDown()"
onmousemove="handleMouseMove()"
onmouseout="handleMouseOut()"
onmouseup="handleMouseUp()"
ontouchstart="handleTouchStart()"
ontouchmove="handleTouchMove()"
ontouchend="handleTouchEnd()">
</div>
Move over box for coordinates relative to top left of box.<br>
Hold mouse down or touch to change color.<br>
Drag to turn on coordinates relative to top left of page.
Prefer using Vue.js? I do! Then your HTML would look like this:
<div #mousedown="handleMouseDown"
#mousemove="handleMouseMove"
#mouseup="handleMouseUp"
#touchstart.stop.prevent="handleTouchStart"
#touchmove.stop.prevent="handleTouchMove"
#touchend.stop.prevent="handleTouchEnd">
None of the above answers are satisfactory IMO, so here's what I use:
// Cross-browser AddEventListener
function ael(e, n, h){
if( e.addEventListener ){
e.addEventListener(n, h, true);
}else{
e.attachEvent('on'+n, h);
}
}
var touch = 'ontouchstart' in document.documentElement; // true if touch device
var mx, my; // always has current mouse position IN WINDOW
if(touch){
ael(document, 'touchmove', function(e){var ori=e;mx=ori.changedTouches[0].pageX;my=ori.changedTouches[0].pageY} );
}else{
ael(document, 'mousemove', function(e){mx=e.clientX;my=e.clientY} );
}
// local mouse X,Y position in element
function showLocalPos(e){
document.title = (mx - e.getBoundingClientRect().left)
+ 'x'
+ Math.round(my - e.getBoundingClientRect().top);
}
And if you ever need to know the current Y scrolling position of page :
var yscroll = window.pageYOffset
|| (document.documentElement && document.documentElement.scrollTop)
|| document.body.scrollTop; // scroll Y position in page
Taken from this tutorial, with corrections made thanks to the top comment:
function getMousePos( canvas, evt ) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor( ( evt.clientX - rect.left ) / ( rect.right - rect.left ) * canvas.width ),
y: Math.floor( ( evt.clientY - rect.top ) / ( rect.bottom - rect.top ) * canvas.height )
};
}
Use on a canvas as follows:
var canvas = document.getElementById( 'myCanvas' );
canvas.addEventListener( 'mousemove', function( evt ) {
var mousePos = getMousePos( canvas, evt );
} );
canvas.onmousedown = function(e) {
pos_left = e.pageX - e.currentTarget.offsetLeft;
pos_top = e.pageY - e.currentTarget.offsetTop;
console.log(pos_left, pos_top)
}
HTMLElement.offsetLeft
The HTMLElement.offsetLeft read-only property returns the number of pixels that the upper left corner of the current element is offset to the left within the HTMLElement.offsetParent node.
For block-level elements, offsetTop, offsetLeft, offsetWidth, and offsetHeight describe the border box of an element relative to the offsetParent.
However, for inline-level elements (such as span) that can wrap from one line to the next, offsetTop and offsetLeft describe the positions of the first border box (use Element.getClientRects() to get its width and height), while offsetWidth and offsetHeight describe the dimensions of the bounding border box (use Element.getBoundingClientRect() to get its position). Therefore, a box with the left, top, width and height of offsetLeft, offsetTop, offsetWidth and offsetHeight will not be a bounding box for a span with wrapped text.
HTMLElement.offsetTop
The HTMLElement.offsetTop read-only property returns the distance of the current element relative to the top of the offsetParent node.
MouseEvent.pageX
The pageX read-only property returns the X (horizontal) coordinate in pixels of the event relative to the whole document. This property takes into account any horizontal scrolling of the page.
MouseEvent.pageY
The MouseEvent.pageY read-only property returns the Y (vertical) coordinate in pixels of the event relative to the whole document. This property takes into account any vertical scrolling of the page.
For further explanation, please see the Mozilla Developer Network:
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop
const findMousePositionRelativeToElement = (e) => {
const xClick = e.clientX - e.currentTarget.offsetLeft;
const yClick = e.clientY - e.currentTarget.offsetTop;
console.log(`x: ${xClick}`);
console.log(`y: ${yClick}`);
// or
const rect = e.currentTarget.getBoundingClientRect();
const xClick2 = e.clientX - rect.left;
const yClick2 = e.clientY - rect.top;
console.log(`x2: ${xClick2}`);
console.log(`y2: ${yClick2}`);
}
I realise I'm a little late , but this works with PURE javascript, and it even gives you the coordinates of the pointer within the element if the element is bigger than the viewport and the user has scrolled.
var element_offset_x ; // The distance from the left side of the element to the left of the content area
....// some code here (function declaration or element lookup )
element_offset_x = element.getBoundingClientRect().left - document.getElementsByTagName("html")[0].getBoundingClientRect().left ;
....// code here
function mouseMoveEvent(event)
{
var pointer_location = (event.clientX + window.pageXOffset) - element_offset_x ;
}
How it works.
The first thing we do is get the location of the HTML element (the content area) relative to the current viewport. If the page has scrollbars and is scrolled, then the number returned by getBoundingClientRect().left for the html tag will be negative. We then use this number to compute the distance between the element and the left of the content area. With element_offset_x = element.getBoundingClientRect().left......;
Knowing the distance of the element from the content area. event.clientX gives us the distance of the pointer from the viewport. It is important to understand that the viewport and the content area are two different entities, the viewport can move if the page is scrolled. Hence, clientX will return the SAME number even if the page is scrolled.
To compensate for this , we need to add the x position of the pointer (relative to the viewport) , to the x position of the viewport (relative to the content area ). The X position of the viewport is found with window.pageXOffset.
Based on #Spider's solution, my non JQuery version is this:
// Get the container element's bounding box
var sides = document.getElementById("container").getBoundingClientRect();
// Apply the mouse event listener
document.getElementById("canvas").onmousemove = (e) => {
// Here 'self' is simply the current window's context
var x = (e.clientX - sides.left) + self.pageXOffset;
var y = (e.clientY - sides.top) + self.pageYOffset;
}
This works both with scrolling and zooming (in which case sometimes it returns floats).
You can use getBoudingClientRect() of the relative parent.
document.addEventListener("mousemove", (e) => {
let xCoord = e.clientX - e.target.getBoundingClientRect().left + e.offsetX
let yCoord = e.clientY - e.target.getBoundingClientRect().top + e.offsetY
console.log("xCoord", xCoord, "yCoord", yCoord)
})
Use this method to get mouse position quickly:
Object.defineProperty(MouseEvent.prototype, "mouseX", {
get() {
return this.clientX - this.currentTarget.getBoundingClientRect().left;
}
});
Object.defineProperty(MouseEvent.prototype, "mouseY", {
get() {
return this.clientY - this.currentTarget.getBoundingClientRect().top;
}
});
example:
document.body.onmousemove=function(e){console.log(e.mouseX,e.mouseY)}
The mouse coordinates inside a canvas can be obtained thanks to event.offsetX and event.offsetY. Here's a little snippet to prove my point:
c=document.getElementById("c");
ctx=c.getContext("2d");
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
c.addEventListener("mousemove",function(mouseEvt){
// the mouse's coordinates on the canvas are just below
x=mouseEvt.offsetX;
y=mouseEvt.offsetY;
// the following lines draw a red square around the mouse to prove it
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
ctx.fillStyle="red";
ctx.fillRect(x-5,y-5,10,10);
});
body {
background-color: blue;
}
canvas {
position: absolute;
top: 50px;
left: 100px;
}
<canvas id="c" width="100" height="100"></canvas>
I implemented an other solution that I think is very simple so I thought I'd share with you guys.
So, the problem for me was that the dragged div would jump to 0,0 for the mouse cursor. So I needed to capture the mouses position on the div to adjust the divs new position.
I read the divs PageX and PageY and set the top and left of the according to that and then to get the values to adjust the coordinates to keep the cursor in the initial position in the div I use a onDragStart listener and store the e.nativeEvent.layerX and e.nativeEvent.layerY that only in the initial trigger gives you the mouses position within the draggable div.
Example code :
onDrag={(e) => {
let newCoords;
newCoords = { x: e.pageX - this.state.correctionX, y: e.pageY - this.state.correctionY };
this.props.onDrag(newCoords, e, item.id);
}}
onDragStart={
(e) => {
this.setState({
correctionX: e.nativeEvent.layerX,
correctionY: e.nativeEvent.layerY,
});
}
I hope this will help someone that went through the same problems I went through :)
function myFunction(e) {
var x = e.clientX - e.currentTarget.offsetLeft ;
var y = e.clientY - e.currentTarget.offsetTop ;
}
this works ok!
You can simply use jQuery’s event.pageX and event.pageY with the method offset() of jQuery to get the position of the mouse relative to an element.
$(document).ready(function() {
$("#myDiv").mousemove(function(event){
var X = event.pageX - $(this).offset().left;
var Y = event.pageY - $(this).offset().top;
$(".cordn").text("(" + X + "," + Y + ")");
});
});
You can see an example here: How to find mouse position relative to element
you can get it by
var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
var xCoor = e.clientX;
var yCoor = e.clientY;
}
You have to know the structure of your page, because if your canvas is a child of a div which in turn is a child of another div... then the story gets more complicated. Here's my code for a canvas which is inside 2 levels of div s:
canvas.addEventListener("click", function(event) {
var x = event.pageX - (this.offsetLeft + this.parentElement.offsetLeft);
var y = event.pageY - (this.offsetTop + this.parentElement.offsetTop);
console.log("relative x=" + x, "relative y" + y);
});
Original answer said to put it in an iframe. The better solution is to use the events offsetX and offsetY on a canvas that has the padding set to 0px.
<html>
<body>
<script>
var main=document.createElement('canvas');
main.width="200";
main.height="300";
main.style="padding:0px;margin:30px;border:thick dashed red";
document.body.appendChild(main);
// adding event listener
main.addEventListener('mousemove',function(e){
var ctx=e.target.getContext('2d');
var c=Math.floor(Math.random()*0xFFFFFF);
c=c.toString(16); for(;c.length<6;) c='0'+c;
ctx.strokeStyle='#'+c;
ctx.beginPath();
ctx.arc(e.offsetX,e.offsetY,3,0,2*Math.PI);
ctx.stroke();
e.target.title=e.offsetX+' '+e.offsetY;
});
// it worked! move mouse over window
</script>
</body>
</html>
Based on #Patrick Boos solution but fixing potential problem with intermediate scrollbars.
export function getRelativeCoordinates(event: MouseEvent, referenceElement: HTMLElement) {
const position = {
x: event.pageX,
y: event.pageY,
};
const offset = {
left: referenceElement.offsetLeft,
top: referenceElement.offsetTop,
};
let reference = referenceElement.offsetParent as HTMLElement;
while (reference) {
offset.left += reference.offsetLeft;
offset.top += reference.offsetTop;
reference = reference.offsetParent as HTMLElement;
}
const scrolls = {
left: 0,
top: 0,
};
reference = event.target as HTMLElement;
while (reference) {
scrolls.left += reference.scrollLeft;
scrolls.top += reference.scrollTop;
reference = reference.parentElement as HTMLElement;
}
return {
x: position.x + scrolls.left - offset.left,
y: position.y + scrolls.top - offset.top,
};
}
I had to get the cursor position inside a very wide div with scrollbar. The objective was to drag elements to any position of the div.
To get the mouse position on a far away position deep in the scrolling.
$('.canvas').on('mousemove', function(e){
$(dragElement).parent().css('top', e.currentTarget.scrollTop + e.originalEvent.clientY );
$(dragElement).parent().css('left', e.currentTarget.scrollLeft + e.originalEvent.clientX )
});
As I didnt find a solution that would help you get it if you append it into a parents element where you have a e.g. selection.
This is what I did:
let positions = {
x: event.pageX,
y: event.pageY - event.currentTarget.getBoundingClientRect().top + event.currentTarget.offsetTop
}
Here is what I got.
$(".some-class").click(function(e) {
var posx = 0;
var posy = 0;
posx = e.pageX;
posy = e.pageY;
alert(posx);
alert(posy);
});
You can scroll to an element using a url with a hashtag and the elements ID:
window.location.href = "#ID"
This will scrol so that the top of the element is at the top of the browser. How would I scroll to an element so that it's vertically centered?
you can scroll up right after the navigation happens:
addEventListener("hashchange", function(){
setTimeout(function(){
document[
document.documentElement.scrollTop ?
"documentElement":
"body"
].scrollTop-= (innerHeight/2.1);
}, 1);
}, false);
this will cause the focused element to appear half-way up the screen, vertically centered.
the 2.1 causes it to scroll just under half the screen, since there will be some room at the top already. you can adjust the ".1" to match your desired effect (baseline, middle, etc).
obligatory fiddle link: http://jsfiddle.net/ckhafLzq/2/
This is what I have achieved:
function centerScroll(element) {
if (!(element instanceof Element)) {
throw new TypeError("Element expected");
}
var bodyRect = document.body.getBoundingClientRect();
var elementRect = element.getBoundingClientRect();
var left = elementRect.left - bodyRect.left;
var top = elementRect.top - bodyRect.top;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var elementWidth = element.offsetWidth;
var elementHeight = element.offsetHeight;
var x = left - Math.max(0, (windowWidth - elementWidth) / 2);
var y = top - Math.max(0, (windowHeight - elementHeight) / 2);
window.scrollTo(x, y);
return [x, y];
}
No, there's no built-in way, you'd have to write that yourself:
function center_element_vertically(elt) {
var rect = elt.getBoundingClientRect();
window.scrollTo(0, rect.top + window.pageYOffset -
(window.innerHeight - rect.height)/2);
}
Alternatives without writing your own code: you could scroll so that the element was at the bottom by passing false to scrollIntoView, or scroll only if the element is not already visible by calling scrollIntoViewIfNeeded, available only in Chrome AFAIK.
I want to know how to use JavaScript to get the distance of an element from the top of the page not the parent element.
http://jsfiddle.net/yZGSt/1/
var elDistanceToTop = window.pageYOffset + el.getBoundingClientRect().top
In my experience document.body.scrollTop doesn't always return the current scroll position (for example if the scrolling actually happens on a different element).
offsetTop only looks at the element's parent. Just loop through parent nodes until you run out of parents and add up their offsets.
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
while(element) {
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
UPDATE: This answer has some problems, values will have tiny differences compare to what it should be and will not work correctly in some cases.
Check #eeglbalazs's answer, which is accurate.
Here is some interesting code for you :)
window.addEventListener('load', function() {
//get the element
var elem = document.getElementById('test');
//get the distance scrolled on body (by default can be changed)
var distanceScrolled = document.body.scrollTop;
//create viewport offset object
var elemRect = elem.getBoundingClientRect();
//get the offset from the element to the viewport
var elemViewportOffset = elemRect.top;
//add them together
var totalOffset = distanceScrolled + elemViewportOffset;
//log it, (look at the top of this example snippet)
document.getElementById('log').innerHTML = totalOffset;
});
#test {
width: 100px;
height: 100px;
background: red;
margin-top: 100vh;
}
#log {
position: fixed;
top: 0;
left: 0;
display: table;
background: #333;
color: #fff;
}
html,
body {
height: 2000px;
height: 200vh;
}
<div id="log"></div>
<div id="test"></div>
Use offsetTop
document.getElementById("foo").offsetTop
Demo
offsetTop doesn’t get the distance to the top of the page, but rather to the top of the closest parent element that has a specified position.
You can use a simple technique that adds up the offsetTop of all the parent element of the element you are interested in to get the distance.
// Our element
var elem = document.querySelector('#some-element');
// Set our distance placeholder
var distance = 0;
// Loop up the dom
do {
// Increase our distance counter
distance += elem.offsetTop;
// Set the element to it's parent
elem = elem.offsetParent;
} while (elem);
distance = distance < 0 ? 0 : distance;
Original code from https://gomakethings.com/how-to-get-an-elements-distance-from-the-top-of-the-page-with-vanilla-javascript/
This oneliner seems to work nice
document.getElementById("el").getBoundingClientRect().top + window.scrollY
your fiddle updated
var distanceTop = element.getBoundingClientRect().top;
For details vist a link:
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
**For anchor links (href="/#about") to anchor <div id="about"> read part 3.
1 (distance_from_top)
Less than 30 seconds solution (Two lines of code "hello world"):
get your element:
var element = document.getElementById("hello");
Get getBoundingClientRect ();
The Element.getBoundingClientRect() method returns the size of an
element and its position relative to the viewport. https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
var rect = element.getBoundingClientRect();
Return object:
Dot notation top
var distance_from_top = rect.top; /* 1007.9971313476562 */
Thats it.
2 (window.scrollTo)
StackOverflow nightmare 2 - set scroll position to this value
Again "hello world" (8,000 answers out there - 7,999 not working or to complex).
https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo
window.scrollTo({
top: element.getBoundingClientRect().top,
behavior: 'smooth'
});
Add offset value to top if you want (For sticky navbars).
"Hello World" code snippet (Get distance from top viewport + click to scrollTo)
var element = document.getElementById("hello");
var rect = element.getBoundingClientRect();
var distance_from_top = rect.top; /* 50px */
console.log(distance_from_top);
function scrollTovView(){
window.scrollTo({
top: distance_from_top,
behavior: 'smooth'
});
}
div{
text-align:center;
border: 1px solid lightgray;
}
<button onclick="scrollTovView()">scrollTo to red DIV</button>
<div style="height: 50px;">50px height</div>
<div id="hello" style="width: 500px; height: 500px; background: red;"></div>
3 (scrollTo & anchors)
scrollTo "conflict" with main anchor navbars
This trick is very buggy if, for example, you use this URL:
www.mysite/about#hello
to
<div id="hello">hello</div>
top is 0 or buggy (The HTML moves to hello section).
window.scrollTo({
top: element.getBoundingClientRect().top,
behavior: 'smooth'
});
For this code to work you should add:
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
Basic example her:
https://www.w3schools.com/howto/howto_css_smooth_scroll.asp
Although it is quite an old discussion, but this works pretty well on chrome / firefox / safari browsers:
window.addEventListener('scroll', function() {
var someDiv = document.getElementById('someDiv');
var distanceToTop = someDiv.getBoundingClientRect().top;
});
Check it out on JSFiddle
scroll to element's top position;
var rect = element.getBoundingClientRect();
var offsetTop = window.pageYOffset + rect.top - rect.height;
document.getElementById("id").offsetTop
(SOURCE : Determine distance from the top of a div to top of window with javascript )
<script type="text/javascript">
var myyElement = document.getElementById("myyy_bar"); //your element
var EnableConsoleLOGS = true; //to check the results in Browser's Inspector(Console), whenever you are scrolling
// ==============================================
window.addEventListener('scroll', function (evt) {
var Positionsss = GetTopLeft ();
if (EnableConsoleLOGS) { console.log(Positionsss); }
});
function GetOffset (object, offset) {
if (!object) return;
offset.x += object.offsetLeft; offset.y += object.offsetTop;
GetOffset (object.offsetParent, offset);
}
function GetScrolled (object, scrolled) {
if (!object) return;
scrolled.x += object.scrollLeft; scrolled.y += object.scrollTop;
if (object.tagName.toLowerCase () != "html") { GetScrolled (object.parentNode, scrolled); }
}
function GetTopLeft () {
var offset = {x : 0, y : 0}; GetOffset (myyElement, offset);
var scrolled = {x : 0, y : 0}; GetScrolled (myyElement.parentNode, scrolled);
var posX = offset.x - scrolled.x; var posY = offset.y - scrolled.y;
return {lefttt: posX , toppp: posY };
}
// ==============================================
</script>
This function returns distance from top of the page, even if your window is scrolled. It can be used in event listeners.
const getElementYOffset = (element) => {
const scrollOnWindow =
window.pageYOffset !== undefined
? window.pageYOffset
: (document.documentElement || document.body.parentNode || document.body)
.scrollTop;
const rect = element.getBoundingClientRect();
let distanceFromTopOfPage = rect.top;
if (scrollOnWindow !== 0) {
distanceFromTopOfPage = rect.top + scrollOnWindow;
}
return distanceFromTopOfPage;
};
You only need this line
document.getElementById("el").getBoundingClientRect().top
in which "el" is the element.
Since window.pageYOffset is a legacy alias of window.scrollY, eeglbalazs answer can be improved to:
const elDistanceToTop = window.scrollY + el.getBoundingClientRect().top;
Using jQuery's offset() method:
$(element).offset().top
Example: http://jsfiddle.net/yZGSt/3/
What's the easiest way to determine an elements position relative to the document/body/browser window?
Right now I'm using .offsetLeft/offsetTop, but this method only gives you the position relative to the parent element, so you need to determine how many parents to the body element, to know the position relaltive to the body/browser window/document position.
This method is also to cumbersome.
You can get top and left without traversing DOM like this:
function getCoords(elem) { // crossbrowser version
var box = elem.getBoundingClientRect();
var body = document.body;
var docEl = document.documentElement;
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
var clientTop = docEl.clientTop || body.clientTop || 0;
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return { top: Math.round(top), left: Math.round(left) };
}
You can use element.getBoundingClientRect() to retrieve element position relative to the viewport.
Then use document.documentElement.scrollTop to calculate the viewport offset.
The sum of the two will give the element position relative to the document:
element.getBoundingClientRect().top + document.documentElement.scrollTop
You can traverse the offsetParent up to the top level of the DOM.
function getOffsetLeft( elem )
{
var offsetLeft = 0;
do {
if ( !isNaN( elem.offsetLeft ) )
{
offsetLeft += elem.offsetLeft;
}
} while( elem = elem.offsetParent );
return offsetLeft;
}
I've found the following method to be the most reliable when dealing with edge cases that trip up offsetTop/offsetLeft.
function getPosition(element) {
var clientRect = element.getBoundingClientRect();
return {left: clientRect.left + document.body.scrollLeft,
top: clientRect.top + document.body.scrollTop};
}
document-offset (3rd-party script) is interesting and it seems to leverage approaches from the other answers here.
Example:
var offset = require('document-offset')
var target = document.getElementById('target')
console.log(offset(target))
// => {top: 69, left: 108}
I suggest using
element.getBoundingClientRect()
as proposed here
instead of manual offset calculation through offsetLeft, offsetTop and offsetParent. as proposed here
Under some circumstances* the manual traversal produces invalid results. See this Plunker: http://plnkr.co/pC8Kgj
*When element is inside of a scrollable parent with static (=default) positioning.
For those that want to get the x and y coordinates of various positions of an element, relative to the document.
const getCoords = (element, position) => {
const { top, left, width, height } = element.getBoundingClientRect();
let point;
switch (position) {
case "top left":
point = {
x: left + window.pageXOffset,
y: top + window.pageYOffset
};
break;
case "top center":
point = {
x: left + width / 2 + window.pageXOffset,
y: top + window.pageYOffset
};
break;
case "top right":
point = {
x: left + width + window.pageXOffset,
y: top + window.pageYOffset
};
break;
case "center left":
point = {
x: left + window.pageXOffset,
y: top + height / 2 + window.pageYOffset
};
break;
case "center":
point = {
x: left + width / 2 + window.pageXOffset,
y: top + height / 2 + window.pageYOffset
};
break;
case "center right":
point = {
x: left + width + window.pageXOffset,
y: top + height / 2 + window.pageYOffset
};
break;
case "bottom left":
point = {
x: left + window.pageXOffset,
y: top + height + window.pageYOffset
};
break;
case "bottom center":
point = {
x: left + width / 2 + window.pageXOffset,
y: top + height + window.pageYOffset
};
break;
case "bottom right":
point = {
x: left + width + window.pageXOffset,
y: top + height + window.pageYOffset
};
break;
}
return point;
};
Usage
getCoords(document.querySelector('selector'), 'center')
getCoords(document.querySelector('selector'), 'bottom right')
getCoords(document.querySelector('selector'), 'top center')
http://www.quirksmode.org/js/findpos.html Explains the best way to do it, all in all, you are on the right track you have to find the offsets and traverse up the tree of parents.
If you don't mind using jQuery, then you can use offset() function. Refer to documentation if you want to read up more about this function.
I want to make a little painting app using canvas. So I need to find the mouse's position on the canvas.
As I didn't find a jQuery-free answer that I could copy/paste, here's the solution I used:
document.getElementById('clickme').onclick = function(e) {
// e = Mouse click event.
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
console.log("Left? : " + x + " ; Top? : " + y + ".");
}
#clickme {
margin-top: 20px;
margin-left: 100px;
border: 1px solid black;
cursor: pointer;
}
<div id="clickme">Click Me -<br>
(this box has margin-left: 100px; margin-top: 20px;)</div>
JSFiddle of full example
For people using JQuery:
Sometimes, when you have nested elements, one of them with the event attached to it, it can be confusing to understand what your browser sees as the parent. Here, you can specify which parent.
You take the mouse position, and then subtract it from the parent element's offset position.
var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;
If you're trying to get the mouse position on a page inside a scrolling pane:
var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();
Or the position relative to the page:
var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Note the following performance optimisation:
var offset = $('#element').offset();
// Then refer to
var x = evt.pageX - offset.left;
In this way, JQuery does not have to look up #element for each line.
Update
There is a newer, JavaScript-only version in an answer by #anytimecoder -- see also browser support for getBoundingClientRect().
The following calculates the mouse position relation to the canvas element:
const example = document.getElementById('example');
example.onmousemove = function(e) {
const x = e.pageX - e.currentTarget.offsetLeft;
const y = e.pageY - e.currentTarget.offsetTop;
}
There is no answer in pure javascript that returns relative coordinates when the reference element is nested inside others which can be with absolute positioning. Here is a solution to this scenario:
function getRelativeCoordinates (event, referenceElement) {
const position = {
x: event.pageX,
y: event.pageY
};
const offset = {
left: referenceElement.offsetLeft,
top: referenceElement.offsetTop
};
let reference = referenceElement.offsetParent;
while(reference){
offset.left += reference.offsetLeft;
offset.top += reference.offsetTop;
reference = reference.offsetParent;
}
return {
x: position.x - offset.left,
y: position.y - offset.top,
};
}
I tried all these solutions and due to my special setup with a matrix transformed container (panzoom library) none worked. This returns the correct value, even if zoomed and paned:
mouseevent(e) {
const x = e.offsetX,
y = e.offsetY
}
But only if there are no child elements in the way. This can be circumvented by making them 'invisible' to the event, using CSS:
.child {
pointer-events: none;
}
A good write up of the difficulty of this problem can be found here: http://www.quirksmode.org/js/events_properties.html#position
Using the technique that is described there you can find the mouses position in the document. Then you just check to see if it is inside the bounding box of your element, which you can find by calling element.getBoundingClientRect() which will return an object with the following properties: { bottom, height, left, right, top, width }. From there it is trivial to figure out if the even happened inside your element or not.
I came across this question, but in order to make it work for my case (using dragover on a DOM-element (not being canvas in my case)), I found that you only have have to use offsetX and offsetY on the dragover-mouse event.
onDragOver(event){
var x = event.offsetX;
var y = event.offsetY;
}
If you want to get the layerX and layerY related to one element, maybe you could try:
let bbox_rect = document.getElementById("dom-ID").getBoundingClientRect()
let layerX = e.clientX-bbox_rect.left
let layerY = e.clientY-bbox_rect.top
I +1' Mark van Wyk's answer as it got me in the right direction, but didn't quite solve it for me. I still had an offset on painting in elements contained within another element.
FOllowing solved it for me:
x = e.pageX - this.offsetLeft - $(elem).offset().left;
y = e.pageY - this.offsetTop - $(elem).offset().top;
In other words - i simply stacked all the offsets from all elements nested
For those of you developing regular websites or PWAs (Progressive Web Apps) for mobile devices and/or laptops/monitors with touch screens, then you have landed here because you might be used to mouse events and are new to the sometimes painful experience of Touch events... yay!
There are just 3 rules:
Do as little as possible during mousemove or touchmove events.
Do as much as possible during mousedown or touchstart events.
Cancel propagation and prevent defaults for touch events to prevent mouse events from also firing on hybrid devices.
Needless to say, things are more complicated with touch events because there can be more than one and they're more flexible (complicated) than mouse events. I'm only going to cover a single touch here. Yes, I'm being lazy, but it's the most common type of touch, so there.
var posTop;
var posLeft;
function handleMouseDown(evt) {
var e = evt || window.event; // Because Firefox, etc.
posTop = e.target.offsetTop;
posLeft = e.target.offsetLeft;
e.target.style.background = "red";
// The statement above would be better handled by CSS
// but it's just an example of a generic visible indicator.
}
function handleMouseMove(evt) {
var e = evt || window.event;
var x = e.offsetX; // Wonderfully
var y = e.offsetY; // Simple!
e.target.innerHTML = "Mouse: " + x + ", " + y;
if (posTop)
e.target.innerHTML += "<br>" + (x + posLeft) + ", " + (y + posTop);
}
function handleMouseOut(evt) {
var e = evt || window.event;
e.target.innerHTML = "";
}
function handleMouseUp(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
}
function handleTouchStart(evt) {
var e = evt || window.event;
var rect = e.target.getBoundingClientRect();
posTop = rect.top;
posLeft = rect.left;
e.target.style.background = "green";
e.preventDefault(); // Unnecessary if using Vue.js
e.stopPropagation(); // Same deal here
}
function handleTouchMove(evt) {
var e = evt || window.event;
var pageX = e.touches[0].clientX; // Touches are page-relative
var pageY = e.touches[0].clientY; // not target-relative
var x = pageX - posLeft;
var y = pageY - posTop;
e.target.innerHTML = "Touch: " + x + ", " + y;
e.target.innerHTML += "<br>" + pageX + ", " + pageY;
e.preventDefault();
e.stopPropagation();
}
function handleTouchEnd(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
// Yes, I'm being lazy and doing the same as mouseout here
// but obviously you could do something different if needed.
e.preventDefault();
e.stopPropagation();
}
div {
background: yellow;
height: 100px;
left: 50px;
position: absolute;
top: 80px;
user-select: none; /* Disable text selection */
-ms-user-select: none;
width: 100px;
}
<div
onmousedown="handleMouseDown()"
onmousemove="handleMouseMove()"
onmouseout="handleMouseOut()"
onmouseup="handleMouseUp()"
ontouchstart="handleTouchStart()"
ontouchmove="handleTouchMove()"
ontouchend="handleTouchEnd()">
</div>
Move over box for coordinates relative to top left of box.<br>
Hold mouse down or touch to change color.<br>
Drag to turn on coordinates relative to top left of page.
Prefer using Vue.js? I do! Then your HTML would look like this:
<div #mousedown="handleMouseDown"
#mousemove="handleMouseMove"
#mouseup="handleMouseUp"
#touchstart.stop.prevent="handleTouchStart"
#touchmove.stop.prevent="handleTouchMove"
#touchend.stop.prevent="handleTouchEnd">
None of the above answers are satisfactory IMO, so here's what I use:
// Cross-browser AddEventListener
function ael(e, n, h){
if( e.addEventListener ){
e.addEventListener(n, h, true);
}else{
e.attachEvent('on'+n, h);
}
}
var touch = 'ontouchstart' in document.documentElement; // true if touch device
var mx, my; // always has current mouse position IN WINDOW
if(touch){
ael(document, 'touchmove', function(e){var ori=e;mx=ori.changedTouches[0].pageX;my=ori.changedTouches[0].pageY} );
}else{
ael(document, 'mousemove', function(e){mx=e.clientX;my=e.clientY} );
}
// local mouse X,Y position in element
function showLocalPos(e){
document.title = (mx - e.getBoundingClientRect().left)
+ 'x'
+ Math.round(my - e.getBoundingClientRect().top);
}
And if you ever need to know the current Y scrolling position of page :
var yscroll = window.pageYOffset
|| (document.documentElement && document.documentElement.scrollTop)
|| document.body.scrollTop; // scroll Y position in page
Taken from this tutorial, with corrections made thanks to the top comment:
function getMousePos( canvas, evt ) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor( ( evt.clientX - rect.left ) / ( rect.right - rect.left ) * canvas.width ),
y: Math.floor( ( evt.clientY - rect.top ) / ( rect.bottom - rect.top ) * canvas.height )
};
}
Use on a canvas as follows:
var canvas = document.getElementById( 'myCanvas' );
canvas.addEventListener( 'mousemove', function( evt ) {
var mousePos = getMousePos( canvas, evt );
} );
canvas.onmousedown = function(e) {
pos_left = e.pageX - e.currentTarget.offsetLeft;
pos_top = e.pageY - e.currentTarget.offsetTop;
console.log(pos_left, pos_top)
}
HTMLElement.offsetLeft
The HTMLElement.offsetLeft read-only property returns the number of pixels that the upper left corner of the current element is offset to the left within the HTMLElement.offsetParent node.
For block-level elements, offsetTop, offsetLeft, offsetWidth, and offsetHeight describe the border box of an element relative to the offsetParent.
However, for inline-level elements (such as span) that can wrap from one line to the next, offsetTop and offsetLeft describe the positions of the first border box (use Element.getClientRects() to get its width and height), while offsetWidth and offsetHeight describe the dimensions of the bounding border box (use Element.getBoundingClientRect() to get its position). Therefore, a box with the left, top, width and height of offsetLeft, offsetTop, offsetWidth and offsetHeight will not be a bounding box for a span with wrapped text.
HTMLElement.offsetTop
The HTMLElement.offsetTop read-only property returns the distance of the current element relative to the top of the offsetParent node.
MouseEvent.pageX
The pageX read-only property returns the X (horizontal) coordinate in pixels of the event relative to the whole document. This property takes into account any horizontal scrolling of the page.
MouseEvent.pageY
The MouseEvent.pageY read-only property returns the Y (vertical) coordinate in pixels of the event relative to the whole document. This property takes into account any vertical scrolling of the page.
For further explanation, please see the Mozilla Developer Network:
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop
const findMousePositionRelativeToElement = (e) => {
const xClick = e.clientX - e.currentTarget.offsetLeft;
const yClick = e.clientY - e.currentTarget.offsetTop;
console.log(`x: ${xClick}`);
console.log(`y: ${yClick}`);
// or
const rect = e.currentTarget.getBoundingClientRect();
const xClick2 = e.clientX - rect.left;
const yClick2 = e.clientY - rect.top;
console.log(`x2: ${xClick2}`);
console.log(`y2: ${yClick2}`);
}
I realise I'm a little late , but this works with PURE javascript, and it even gives you the coordinates of the pointer within the element if the element is bigger than the viewport and the user has scrolled.
var element_offset_x ; // The distance from the left side of the element to the left of the content area
....// some code here (function declaration or element lookup )
element_offset_x = element.getBoundingClientRect().left - document.getElementsByTagName("html")[0].getBoundingClientRect().left ;
....// code here
function mouseMoveEvent(event)
{
var pointer_location = (event.clientX + window.pageXOffset) - element_offset_x ;
}
How it works.
The first thing we do is get the location of the HTML element (the content area) relative to the current viewport. If the page has scrollbars and is scrolled, then the number returned by getBoundingClientRect().left for the html tag will be negative. We then use this number to compute the distance between the element and the left of the content area. With element_offset_x = element.getBoundingClientRect().left......;
Knowing the distance of the element from the content area. event.clientX gives us the distance of the pointer from the viewport. It is important to understand that the viewport and the content area are two different entities, the viewport can move if the page is scrolled. Hence, clientX will return the SAME number even if the page is scrolled.
To compensate for this , we need to add the x position of the pointer (relative to the viewport) , to the x position of the viewport (relative to the content area ). The X position of the viewport is found with window.pageXOffset.
Based on #Spider's solution, my non JQuery version is this:
// Get the container element's bounding box
var sides = document.getElementById("container").getBoundingClientRect();
// Apply the mouse event listener
document.getElementById("canvas").onmousemove = (e) => {
// Here 'self' is simply the current window's context
var x = (e.clientX - sides.left) + self.pageXOffset;
var y = (e.clientY - sides.top) + self.pageYOffset;
}
This works both with scrolling and zooming (in which case sometimes it returns floats).
You can use getBoudingClientRect() of the relative parent.
document.addEventListener("mousemove", (e) => {
let xCoord = e.clientX - e.target.getBoundingClientRect().left + e.offsetX
let yCoord = e.clientY - e.target.getBoundingClientRect().top + e.offsetY
console.log("xCoord", xCoord, "yCoord", yCoord)
})
Use this method to get mouse position quickly:
Object.defineProperty(MouseEvent.prototype, "mouseX", {
get() {
return this.clientX - this.currentTarget.getBoundingClientRect().left;
}
});
Object.defineProperty(MouseEvent.prototype, "mouseY", {
get() {
return this.clientY - this.currentTarget.getBoundingClientRect().top;
}
});
example:
document.body.onmousemove=function(e){console.log(e.mouseX,e.mouseY)}
The mouse coordinates inside a canvas can be obtained thanks to event.offsetX and event.offsetY. Here's a little snippet to prove my point:
c=document.getElementById("c");
ctx=c.getContext("2d");
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
c.addEventListener("mousemove",function(mouseEvt){
// the mouse's coordinates on the canvas are just below
x=mouseEvt.offsetX;
y=mouseEvt.offsetY;
// the following lines draw a red square around the mouse to prove it
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
ctx.fillStyle="red";
ctx.fillRect(x-5,y-5,10,10);
});
body {
background-color: blue;
}
canvas {
position: absolute;
top: 50px;
left: 100px;
}
<canvas id="c" width="100" height="100"></canvas>
I implemented an other solution that I think is very simple so I thought I'd share with you guys.
So, the problem for me was that the dragged div would jump to 0,0 for the mouse cursor. So I needed to capture the mouses position on the div to adjust the divs new position.
I read the divs PageX and PageY and set the top and left of the according to that and then to get the values to adjust the coordinates to keep the cursor in the initial position in the div I use a onDragStart listener and store the e.nativeEvent.layerX and e.nativeEvent.layerY that only in the initial trigger gives you the mouses position within the draggable div.
Example code :
onDrag={(e) => {
let newCoords;
newCoords = { x: e.pageX - this.state.correctionX, y: e.pageY - this.state.correctionY };
this.props.onDrag(newCoords, e, item.id);
}}
onDragStart={
(e) => {
this.setState({
correctionX: e.nativeEvent.layerX,
correctionY: e.nativeEvent.layerY,
});
}
I hope this will help someone that went through the same problems I went through :)
function myFunction(e) {
var x = e.clientX - e.currentTarget.offsetLeft ;
var y = e.clientY - e.currentTarget.offsetTop ;
}
this works ok!
You can simply use jQuery’s event.pageX and event.pageY with the method offset() of jQuery to get the position of the mouse relative to an element.
$(document).ready(function() {
$("#myDiv").mousemove(function(event){
var X = event.pageX - $(this).offset().left;
var Y = event.pageY - $(this).offset().top;
$(".cordn").text("(" + X + "," + Y + ")");
});
});
You can see an example here: How to find mouse position relative to element
you can get it by
var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
var xCoor = e.clientX;
var yCoor = e.clientY;
}
You have to know the structure of your page, because if your canvas is a child of a div which in turn is a child of another div... then the story gets more complicated. Here's my code for a canvas which is inside 2 levels of div s:
canvas.addEventListener("click", function(event) {
var x = event.pageX - (this.offsetLeft + this.parentElement.offsetLeft);
var y = event.pageY - (this.offsetTop + this.parentElement.offsetTop);
console.log("relative x=" + x, "relative y" + y);
});
Original answer said to put it in an iframe. The better solution is to use the events offsetX and offsetY on a canvas that has the padding set to 0px.
<html>
<body>
<script>
var main=document.createElement('canvas');
main.width="200";
main.height="300";
main.style="padding:0px;margin:30px;border:thick dashed red";
document.body.appendChild(main);
// adding event listener
main.addEventListener('mousemove',function(e){
var ctx=e.target.getContext('2d');
var c=Math.floor(Math.random()*0xFFFFFF);
c=c.toString(16); for(;c.length<6;) c='0'+c;
ctx.strokeStyle='#'+c;
ctx.beginPath();
ctx.arc(e.offsetX,e.offsetY,3,0,2*Math.PI);
ctx.stroke();
e.target.title=e.offsetX+' '+e.offsetY;
});
// it worked! move mouse over window
</script>
</body>
</html>
Based on #Patrick Boos solution but fixing potential problem with intermediate scrollbars.
export function getRelativeCoordinates(event: MouseEvent, referenceElement: HTMLElement) {
const position = {
x: event.pageX,
y: event.pageY,
};
const offset = {
left: referenceElement.offsetLeft,
top: referenceElement.offsetTop,
};
let reference = referenceElement.offsetParent as HTMLElement;
while (reference) {
offset.left += reference.offsetLeft;
offset.top += reference.offsetTop;
reference = reference.offsetParent as HTMLElement;
}
const scrolls = {
left: 0,
top: 0,
};
reference = event.target as HTMLElement;
while (reference) {
scrolls.left += reference.scrollLeft;
scrolls.top += reference.scrollTop;
reference = reference.parentElement as HTMLElement;
}
return {
x: position.x + scrolls.left - offset.left,
y: position.y + scrolls.top - offset.top,
};
}
I had to get the cursor position inside a very wide div with scrollbar. The objective was to drag elements to any position of the div.
To get the mouse position on a far away position deep in the scrolling.
$('.canvas').on('mousemove', function(e){
$(dragElement).parent().css('top', e.currentTarget.scrollTop + e.originalEvent.clientY );
$(dragElement).parent().css('left', e.currentTarget.scrollLeft + e.originalEvent.clientX )
});
As I didnt find a solution that would help you get it if you append it into a parents element where you have a e.g. selection.
This is what I did:
let positions = {
x: event.pageX,
y: event.pageY - event.currentTarget.getBoundingClientRect().top + event.currentTarget.offsetTop
}
Here is what I got.
$(".some-class").click(function(e) {
var posx = 0;
var posy = 0;
posx = e.pageX;
posy = e.pageY;
alert(posx);
alert(posy);
});