Tìm vị trí chuột liên quan đến yếu tố


244

Tôi muốn làm một ứng dụng vẽ tranh nhỏ bằng vải. Vì vậy, tôi cần tìm vị trí của chuột trên khung vẽ.


2
Giải pháp đầy đủ: acko.net/blog/ Từ
edA-qa mort-ora-y

3
Tôi thích cách ngắn, nhưng giải thích tất cả mọi thứ bài này.
dwjohnston

Điều này thực sự cũ, nhưng tôi mới bắt đầu một dự án GitHub, trong số những thứ khác, thực hiện chính xác những gì bạn cần: brainlessdeveloper.com/mouse-move-interaction-spot-js
Fausto NA

Câu trả lời:


177

Đối với những người sử dụng JQuery:

Đôi khi, khi bạn có các phần tử lồng nhau, một trong số chúng có sự kiện được đính kèm, có thể khó hiểu khi trình duyệt của bạn xem là phần tử mẹ. Ở đây, bạn có thể chỉ định cha mẹ.

Bạn lấy vị trí chuột và sau đó trừ nó khỏi vị trí bù của phần tử cha.

var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;

Nếu bạn đang cố lấy vị trí chuột trên một trang bên trong ngăn cuộn:

var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();

Hoặc vị trí liên quan đến trang:

var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();

Lưu ý tối ưu hóa hiệu suất sau:

var offset = $('#element').offset();
// Then refer to 
var x = evt.pageX - offset.left;

Theo cách này, JQuery không phải tìm kiếm #element từng dòng.

Cập nhật

Có một phiên bản mới hơn, chỉ có JavaScript bên dưới bởi @anytimecoder bên dưới dành cho các trình duyệt hỗ trợ getBoundingClientRect () .


7
Nó có hiệu quả với bạn không @ben, tôi đánh giá cao "Câu trả lời đúng" hoặc nhận xét về những gì vẫn không hiệu quả với bạn. Có lẽ tôi có thể giúp thêm.
Sparkyspider

8
Nên tránh sử dụng $ ('bộ chọn') trong trình xử lý sự kiện, trừ khi bạn muốn mã rất chậm. Chọn trước phần tử của bạn và sử dụng tham chiếu được chọn trước trong trình xử lý của bạn. Tương tự với $ (window) làm điều đó một lần và lưu trữ nó.
Austin Pháp

2
đây không phải là một đề cập cần thiết: nếu bạn đang sao chép đoạn mã trên, hãy nhớ sửa var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();thànhvar y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Raj Nathani

77
Làm thế nào đó có thể là câu trả lời vì câu hỏi không liên quan gì đến jQuery?
FlorianB

2
@Black nhưng một số người hỏi những thứ trong javascript thay vì jquery vì jquery có thể không tương thích trong môi trường của họ.
dbrree

307

Vì tôi không tìm thấy câu trả lời không có jQuery mà tôi có thể sao chép / dán, đây là giải pháp tôi đã sử dụng:

function clickEvent(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.
}

Ví dụ đầy đủ


2
Bạn cần làm tròn các chỉnh lưu giới hạn để đảm bảo các giá trị nguyên với phương thức này.
Jake Cobb

2
Chỉnh sửa mới sẽ khắc phục các sự cố cuộn (sử dụng clientX / Y)
Erik Koopmans

6
Câu trả lời này nên được bình chọn. Cảm ơn bạn anytimecoder và @ErikKoopmans.
Ivan

3
PSA: Nhận xét của @mpen đã lỗi thời; phương pháp này KHÔNG hoạt động, ngay cả trong trường hợp cuộn. Xem phiên bản cập nhật của Fiddle của họ: jsfiddle.net/6wcsovp2
Xharlie

4
Cảm ơn bạn! Một lưu ý: bạn cần e.currentTarget, không phải e.target. Nếu không, các yếu tố trẻ em sẽ ảnh hưởng đến nó
Maxim Georgievskiy

60

Sau đây tính toán mối quan hệ vị trí chuột với phần tử canvas:

var example = document.getElementById('example'); 
example.onmousemove = function(e) { 
    var x = e.pageX - this.offsetLeft; 
    var y = e.pageY - this.offsetTop; 
}

Trong ví dụ này, thisđề cập đến examplephần tử và eonmousemovesự kiện.


83
Có thể đó là tôi nhưng hai dòng mã sử dụng từ khóa "này" thiếu ngữ cảnh?
Deratrius

9
Chắc chắn thiếu bối cảnh. 'e' là sự kiện và 'đây' là yếu tố mà sự kiện này gắn liền với var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
Nick Bisby

22
Điều này không hoạt động nếu một số yếu tố hậu duệ sử dụng định vị tương đối hoặc tuyệt đối.
edA-qa mort-ora-y

12
Bạn có thể chuyển ra thistới e.currentTarget, mà sẽ giúp bạn có được vị trí tương đối so với các yếu tố mà bạn thêm người nghe sự kiện vào.
Linus Unnebäck

2
Điều này dường như cung cấp cho vị trí tương đối với phần có thể nhìn thấy của phần tử, không phải toàn bộ phần tử. Có cách nào để phù hợp với điều đó nếu một phần của phần tử không thể nhìn thấy trong chế độ xem và có thanh cuộn, v.v.?
frabjous

37

Không có câu trả lời trong javascript thuần trả về tọa độ tương đối khi phần tử tham chiếu được lồng bên trong các phần tử khác có thể được định vị tuyệt đối. Đây là một giải pháp cho kịch bản này:

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,
  }; 

}

3
Tôi không nghĩ rằng nó tính đến htmlyếu tố bù trừ
apieceofbart

3
Hoạt động tuyệt vời với các container cuộn, chỉ với một chút thay đổi: thay thế while(reference !== undefined)bằng while(reference). Trong Chrome ít nhất, offsetParent cuối cùng không tồn tại undefined, nhưng null. Chỉ cần kiểm tra xem sự referencethật có đảm bảo nó hoạt động với cả hai undefinednull.
blex

Tôi sẽ cho +1 khác nếu tôi có thể, vì cho tôi biết có một offsetParenttài sản, hóa ra nó cũng rất hữu ích trong các tình huống khác!
FonzTech

Nói chung, kiểm tra chống lại không xác định thường là một ý tưởng tồi
Juan Mendes

Tôi nghĩ rằng bạn cần phải trừ scrollLeftscrollTopđể bù đắp cho con cháu di chuyển.
Robert

20

Một bài viết hay về khó khăn của vấn đề này có thể được tìm thấy ở đây: http://www.quirksmode.org/js/events_properIES.html#poseition

Sử dụng kỹ thuật được mô tả ở đó, bạn có thể tìm thấy vị trí chuột trong tài liệu. Sau đó, bạn chỉ cần kiểm tra xem nó có nằm trong hộp giới hạn của phần tử của bạn hay không, bằng cách gọi element.getBoundingClientRect()nó sẽ trả về một đối tượng có các thuộc tính sau : { bottom, height, left, right, top, width }. Từ đó, thật tầm thường để biết liệu thậm chí có xảy ra bên trong yếu tố của bạn hay không.


1
Đáng buồn thay, điều này thất bại nếu có bất kỳ loại luân chuyển nào đang diễn ra
Eric

17

Tôi đã thử tất cả các giải pháp này và do thiết lập đặc biệt của tôi với một thùng chứa biến đổi ma trận (thư viện panzoom) không có hiệu quả. Điều này trả về giá trị chính xác, ngay cả khi phóng to và xoay:

mouseevent(e) {
 const x = e.offsetX,
       y = e.offsetY
}

Nhưng chỉ khi không có yếu tố con theo cách này. Điều này có thể được phá vỡ bằng cách làm cho chúng 'vô hình' đối với sự kiện, sử dụng CSS:

.child {
   pointer-events: none;
}

3
Đây chắc chắn là cách để làm điều này vào năm 2019. Các câu trả lời khác đều được nạp với hành lý cũ nát.
Colin D

1
@ColinD cảm ơn bạn! Tôi quên thêm rằng cái này cũng hoạt động trong IE11.
Fabian von Ellerts

Điều này làm việc cho tôi. Tuy nhiên, tôi nghi ngờ rằng 1) Rất ít câu trả lời 2) câu trả lời được đánh giá cao hơn phức tạp hơn và 3) Tôi thấy không có nhược điểm nào được giải thích. Có ai biết bất kỳ con sử dụng phương pháp này?
Đánh dấu E

1
@MarkE Không có gì đáng nghi ngờ về điều đó. Đây là một trong nhiều lỗi của StackOverflow. Những câu trả lời mà bạn nhìn thấy ở đầu đã được đăng nhiều năm trước câu trả lời này ở đây, vì vậy họ đã đạt được động lực bỏ phiếu rất lớn. Một khi câu trả lời đạt được đà này, nó rất khó và khá hiếm để đánh bại nó.
Jack Giffin

9

Tôi đã gặp câu hỏi này, nhưng để làm cho nó hoạt động cho trường hợp của tôi (sử dụng tính năng kéo trên phần tử DOM (không phải là canvas trong trường hợp của tôi)), tôi thấy rằng bạn chỉ phải sử dụng offsetXoffsetYtrong sự kiện kéo chuột .

onDragOver(event){
 var x = event.offsetX;
 var y = event.offsetY;
}

2
Nó hiệu quả tuyệt vời đối với tôi. Tại sao không có ai ủng hộ điều này? Tôi tự hỏi nếu có bất kỳ cạm bẫy. Nếu tôi tìm thấy bất kỳ tôi sẽ báo cáo lại!
cá chẽm

7
event.offsetX liên quan đến phần tử mà con trỏ chuột hiện đang kết thúc, không phải là phần tử có trình nghe kéo theo được đính kèm. Nếu bạn không có cấu trúc phần tử lồng nhau thì điều này tốt, nhưng nếu bạn làm vậy thì điều này sẽ không hiệu quả.
opsb

7

Tôi +1 'Câu trả lời của Mark van Wyk vì nó đã đưa tôi đi đúng hướng, nhưng không giải quyết được cho tôi. Tôi vẫn có một khoảng trống trên bức tranh trong các yếu tố chứa trong một yếu tố khác.

FOllowing đã giải quyết nó cho tôi:

        x = e.pageX - this.offsetLeft - $(elem).offset().left;
        y = e.pageY - this.offsetTop - $(elem).offset().top;

Nói cách khác - tôi chỉ đơn giản xếp chồng tất cả các phần bù từ tất cả các phần tử lồng nhau


+1 cho bạn! Đây là câu trả lời tôi đang tìm kiếm. Tôi có hai bức tranh xếp chồng lên nhau và tọa độ đều sai vì các div khác. Tôi biết đây là vấn đề, nhưng không biết logic / phương trình để bù nó. Bạn chỉ cần khắc phục vấn đề của tôi quá! = D cảm ơn!
Partack

5

Không có câu trả lời nào ở trên là IMO thỏa đáng, vì vậy đây là những gì tôi sử dụng:

// 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);
}

Và nếu bạn cần biết vị trí cuộn Y hiện tại của trang:

var yscroll = window.pageYOffset
        || (document.documentElement && document.documentElement.scrollTop)
        || document.body.scrollTop; // scroll Y position in page

4

Đối với những người bạn đang phát triển trang web thông thường hoặc PWAs (Ứng dụng web lũy tiến) cho thiết bị di động và / hoặc máy tính xách tay / màn hình có màn hình cảm ứng, thì bạn đã đến đây vì bạn có thể quen với các sự kiện chuột và mới đối với trải nghiệm đôi khi đau đớn của Touch sự kiện ... yay!

Chỉ có 3 quy tắc:

  1. Làm ít nhất có thể trong mousemovehoặc touchmovesự kiện.
  2. Làm càng nhiều càng tốt trong khi mousedownhoặc touchstartsự kiện.
  3. Hủy bỏ lan truyền và ngăn mặc định cho các sự kiện chạm để ngăn các sự kiện chuột cũng bắn vào các thiết bị lai.

Không cần phải nói, mọi thứ phức tạp hơn với touchcác sự kiện vì có thể có nhiều hơn một và chúng linh hoạt (phức tạp) hơn các sự kiện chuột. Tôi sẽ chỉ bao gồm một liên lạc duy nhất ở đây. Vâng, tôi đang lười biếng, nhưng đó là loại cảm ứng phổ biến nhất, vì vậy có.

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.

Thích sử dụng Vue.js ? Tôi làm! Sau đó, HTML của bạn sẽ trông như thế này:

<div @mousedown="handleMouseDown"
     @mousemove="handleMouseMove"
     @mouseup="handleMouseUp"
     @touchstart.stop.prevent="handleTouchStart"
     @touchmove.stop.prevent="handleTouchMove"
     @touchend.stop.prevent="handleTouchEnd">

3

bạn có thể lấy nó bằng cách

var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
    var xCoor = e.clientX;
    var yCoor = e.clientY;
}

Điều này sẽ hoạt động trong IE, hay IE vẫn sử dụng window.event thay vì chuyển sự kiện đến đối số đầu tiên của người nghe? chỉnh sửa - Tôi đoán IE dù sao cũng thiếu phần tử canvas cho đến phiên bản 9, nhưng điều này có lẽ vẫn hỗ trợ IE vì những thứ như excanvas ....
Dagg Nợi

21
Điều này sẽ cung cấp tọa độ tương đối với cửa sổ trình duyệt, vẫn cần phải tìm hiểu xem chúng có trong phần tử hay không bằng cách sử dụng phần tử.getBoundingClientRect ()
David W. Keith

cảm ơn bạn đã cho tôi biết về getBoundingClientRect !!!! Tôi không bao giờ nhận ra có một điều như vậy!
Gershom

@ DavidW.Keith bình luận nên thực sự được coi là câu trả lời chính xác!
Ulrik. S

3

Lấy từ hướng dẫn này , với các chỉnh sửa được thực hiện nhờ vào nhận xét hàng đầu:

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 )
    };
}

Sử dụng trên một khung vẽ như sau:

var canvas = document.getElementById( 'myCanvas' );
canvas.addEventListener( 'mousemove', function( evt ) {
    var mousePos = getMousePos( canvas, evt );
} );

3

Tôi nhận ra mình hơi muộn, nhưng điều này hoạt động với javascript PURE và thậm chí nó còn cung cấp cho bạn tọa độ của con trỏ trong phần tử nếu phần tử lớn hơn chế độ xem và người dùng đã cuộn.

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 ; 
}

Làm thế nào nó hoạt động.

Điều đầu tiên chúng ta làm là lấy vị trí của phần tử HTML (vùng nội dung) so với chế độ xem hiện tại. Nếu trang có thanh cuộn và được cuộn, thì số được trả về bởigetBoundingClientRect().left cho thẻ html sẽ âm. Sau đó chúng tôi sử dụng số này để tính khoảng cách giữa phần tử và bên trái của khu vực nội dung. Vớielement_offset_x = element.getBoundingClientRect().left......;

Biết khoảng cách của phần tử từ khu vực nội dung. event.clientXcho chúng ta khoảng cách của con trỏ từ khung nhìn. Điều quan trọng là phải hiểu rằng chế độ xem và khu vực nội dung là hai thực thể khác nhau, chế độ xem có thể di chuyển nếu trang được cuộn. Do đó, clientX sẽ trả về số CÙNG ngay cả khi trang được cuộn.

Để bù cho điều này, chúng ta cần thêm vị trí x của con trỏ (liên quan đến chế độ xem), vào vị trí x của chế độ xem (liên quan đến khu vực nội dung). Vị trí X của khung nhìn được tìm thấy với window.pageXOffset.


1
Cảm ơn bạn đã là người trả lời duy nhất nghĩ về việc cuộn. Cân nhắc thay đổi câu trả lời của bạn để thêm trục y.
frabjous

3

Dựa trên giải pháp của @ Spider, phiên bản không phải JQuery của tôi là:

// 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;
}

Điều này hoạt động cả với cuộn và phóng to (trong trường hợp này đôi khi nó trả về số float).


Tôi sẽ upvote, nhưng không nên là những dấu trừ cho việc bù đắp trang? Hoặc là, hoặc dấu ngoặc đơn xung quanh phần thứ hai?
Chris Sunami hỗ trợ Monica

1

Các tọa độ chuột bên trong một khung vẽ có thể thu được nhờ event.offsetX và event.offsetY. Đây là một đoạn nhỏ để chứng minh quan điểm của tôi:

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>
    


Sẽ không hoạt động nếu một div khác phủ lên khung vẽ, giống như @opsb đã nói
David Peicho

1
canvas.onmousedown = function(e) {
    pos_left = e.pageX - e.currentTarget.offsetLeft;
    pos_top = e.pageY - e.currentTarget.offsetTop;
    console.log(pos_left, pos_top)
}

HTMLEuity.offsetLeft

Các HTMLElement.offsetLeftlợi nhuận thuộc tính chỉ đọc số lượng điểm ảnh góc trên bên trái của phần tử hiện nay được bù đắp bên trái trongHTMLElement.offsetParent nút.

Đối với yếu tố khối cấp, offsetTop, offsetLeft, offsetWidth, và offsetHeightmô tả các hộp biên giới của một phần tử tương đối so với offsetParent.

Tuy nhiên, đối với các phần tử mức nội tuyến (chẳng hạn span) có thể bao bọc từ dòng này sang dòng tiếp theo offsetTopoffsetLeftmô tả vị trí của hộp viền đầu tiên (sử dụng Element.getClientRects()để lấy chiều rộng và chiều cao của nó), trong khi offsetWidthoffsetHeightmô tả kích thước của hộp viền giới hạn (sử dụng Element.getBoundingClientRect()để có được vị trí của nó). Do đó, một hộp với trái, hàng đầu, chiều rộng và chiều cao của offsetLeft, offsetTop, offsetWidthoffsetHeightsẽ không có một hộp bounding cho một khoảng thời với văn bản bọc.

HTMLEuity.offsetTop

Các HTMLElement.offsetTopthuộc tính chỉ đọc trả về khoảng cách của phần tử tương đối hiện tại để phía trên cùng của offsetParentnút.

MouseEvent.pageX

Các pageXthuộc tính chỉ đọc trả về X (ngang) phối hợp theo pixel của sự kiện liên quan đến toàn bộ tài liệu. Thuộc tính này có tính đến bất kỳ cuộn ngang của trang.

MouseEvent.pageY

Các MouseEvent.pageY lợi nhuận chỉ đọc tài sản Y (dọc) phối hợp theo pixel của sự kiện liên quan đến toàn bộ tài liệu. Thuộc tính này có tính đến bất kỳ cuộn dọc của trang.

Để được giải thích thêm, vui lòng xem Mạng của Nhà phát triển Mozilla:

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/HTMLEuity/offsetLeft https://developer.mozilla.org/en-US/docs/Web/API/HTMLEuity/offsetTop


Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
Patrick Hund

Tôi thực sự hy vọng các độc giả trong tương lai sẽ có API JS tính toán điều này cho họ. ;-) Đây có lẽ là câu trả lời đơn giản, đầy đủ, khép kín. Nhận xét mã tự giải thích chỉ là phân tâm lãng phí.
lama12345

Tôi thứ hai yêu cầu giải thích của PatrickHund. Tôi không phải là chuyên gia CSS / JS và biết thêm về các mối quan hệ giữa, ví dụ, pageoffsetsẽ rất hữu ích cho tôi. Cảm ơn bạn đã xem xét yêu cầu này!
cxw

@cxw Ok, bây giờ bạn là downvote thứ 2 (đã có 1 upvote) ... Tôi đã thêm một lời giải thích dài bây giờ, nó dài gấp 10 lần 4 dòng mã. Bạn được chào đón, vui vẻ đọc. Tôi đã xem xét yêu cầu của bạn! : p
lama12345

1
@cxw Tôi đã loay hoay bằng cách thêm một yếu tố định vị tuyệt đối bổ sung và buộc chính phần tử canvas đó ngoài màn hình, vì vậy tôi phải cuộn đến nó, như màn hình ngoài 2000px trái / trên. Không thể lấy mã này để phá vỡ.
lama12345

1

Tôi đã thực hiện một giải pháp khác mà tôi nghĩ là rất đơn giản vì vậy tôi nghĩ tôi muốn chia sẻ với các bạn.

Vì vậy, vấn đề đối với tôi là div được kéo sẽ nhảy lên 0,0 cho con trỏ chuột. Vì vậy, tôi cần phải nắm bắt vị trí chuột trên div để điều chỉnh vị trí mới của div.

Tôi đọc các div PageX và PageY và đặt trên cùng và bên trái theo đó và sau đó để lấy các giá trị để điều chỉnh tọa độ để giữ con trỏ ở vị trí ban đầu trong div tôi sử dụng trình nghe onDragStart và lưu trữ e.nativeEvent .layerXe.nativeEvent.layerY chỉ trong trình kích hoạt ban đầu mới cung cấp cho bạn vị trí chuột trong div có thể kéo được.

Mã ví dụ:

 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,
            });
          }

Tôi hy vọng điều này sẽ giúp được ai đó đã trải qua những vấn đề tương tự mà tôi đã trải qua :)


1
function myFunction(e) {
    var x =  e.clientX - e.currentTarget.offsetLeft ; 
    var y = e.clientY - e.currentTarget.offsetTop ;
}

cái này hoạt động tốt


0

Bạn phải biết cấu trúc của trang của bạn, bởi vì nếu canvas của bạn là con của một div mà đến lượt nó là con của một div khác ... thì câu chuyện trở nên phức tạp hơn. Đây là mã của tôi cho một canvas nằm trong 2 cấp độ của div:

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);

});


0

Câu trả lời ban đầu nói để đặt nó trong iframe. Giải pháp tốt hơn là sử dụng các sự kiện offsetX và offsetY trên khung vẽ có phần đệm được đặt thành 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>

0

Đây là những gì tôi nhận được.

    $(".some-class").click(function(e) {

    var posx = 0;
    var posy = 0;

    posx = e.pageX;
    posy = e.pageY;

    alert(posx);
    alert(posy);
});

0

Bạn có thể sử dụng getBoudingClientRect()của relativecha mẹ.

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)
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.