Znajdź pozycję myszy względem elementu


244

Chcę zrobić małą aplikację do malowania z płótna. Muszę więc znaleźć pozycję myszy na płótnie.


2
Pełne rozwiązanie: acko.net/blog/…
— edA-qa mort-ora-y

3
Uwielbiam jak krótki, ale wyjaśnia wszystko, co ten post jest.
— dwjohnston,

To jest naprawdę stare, ale właśnie rozpocząłem projekt GitHub, który między innymi robi dokładnie to, czego potrzebujesz: brainlessdeveloper.com/mouse-move-interaction-spot-js
— Fausto NA

Odpowiedzi:


177

Dla osób korzystających z JQuery:

Czasami po zagnieżdżeniu elementów, jednego z nich z dołączonym zdarzeniem, zrozumienie tego, co przeglądarka postrzega jako element nadrzędny, może być mylące. Tutaj możesz określić, który rodzic.

Bierzesz pozycję myszy, a następnie odejmujesz ją od pozycji przesunięcia elementu nadrzędnego.

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

Jeśli próbujesz ustawić pozycję myszy na stronie w przewijanym panelu:

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

Lub pozycja względem strony:

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

Zwróć uwagę na następującą optymalizację wydajności:

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

W ten sposób JQuery nie musi szukać #elementkażdej linii.

Aktualizacja

Poniżej znajduje się nowsza wersja, tylko JavaScript, autorstwa @anytimecoder dla przeglądarek obsługujących getBoundingClientRect () .


7
Czy to zadziałało dla ciebie @ben, byłbym wdzięczny za „poprawną odpowiedź” lub komentarz na temat tego, co nadal nie działa. Może mogę pomóc dalej.
— sparkyspider

8
Należy unikać używania $ („selektor”) w procedurze obsługi zdarzeń, chyba że chcesz bardzo powolnego kodu. Wybierz wstępnie element i użyj wstępnie wybranego odwołania w module obsługi. To samo dla $ (okno) zrób to raz i buforuj.
— Austin France,

2
to nie jest konieczne wzmianka: jeśli kopia wklejania powyższy kod, należy pamiętać, aby skorygować var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();dovar y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
— Raj Nathani

77
Jak to może być odpowiedź, skoro pytanie nie ma nic wspólnego z jQuery?
— FlorianB

2
@Czarny, ale niektórzy ludzie pytają rzeczy w javascript zamiast jquery, ponieważ jquery może nie być kompatybilne w ich środowiskach.
— dbrree

307

Ponieważ nie znalazłem odpowiedzi bez jQuery, którą można skopiować / wkleić, oto rozwiązanie, którego użyłem:

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

JSFiddle pełnego przykładu


2
Tą metodą należy zaokrąglić obwiednię ograniczającą, aby zapewnić wartości całkowite.
— Jake Cobb,

2
Nowa edycja powinna rozwiązać problemy z przewijaniem (przy użyciu clientX / Y)
— Erik Koopmans

6
Ta odpowiedź powinna zostać poddana pod głosowanie. Dziękuję anyimecoder i @ErikKoopmans.
— Ivan

3
PSA: komentarz @mpen jest przestarzały; ta metoda DZIAŁA, nawet w przypadku przewijania. Zobacz zaktualizowaną wersję ich Fiddle: jsfiddle.net/6wcsovp2
— Xharlie

4
Dziękuję Ci! Jedna uwaga: potrzebujesz e.currentTarget, a nie e.target. W przeciwnym razie wpłyną na to elementy potomne
— Maxim Georgievskiy,

60

Poniższe oblicza relację położenia myszy do elementu canvas:

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

W tym przykładzie thisodnosi się do exampleelementu i ejest onmousemovezdarzeniem.


83
Może to ja, ale dwa wiersze kodów używających słowa kluczowego „to” nie mają kontekstu?
— Deratrius

9
Zdecydowanie brakuje kontekstu. „e” to wydarzenie, a „to” to element, z którym wydarzenie jest powiązane var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
— Nick Bisby,

22
To nie działa, jeśli jakiś element potomny używa pozycjonowania względnego lub bezwzględnego.
— edA-qa mort-ora-y

12
Możesz się przełączyć thisna e.currentTarget, dzięki czemu uzyskasz pozycję względem elementu, do którego dodano detektor zdarzeń.
— Linus Unnebäck

2
Wydaje się, że daje to pozycję względem widocznej części elementu, a nie całego elementu. Czy istnieje sposób, aby to uwzględnić, jeśli część elementu nie jest widoczna w rzutni i istnieją paski przewijania itp.?
— frabjous

37

W czystym javascript nie ma odpowiedzi, która zwraca względne współrzędne, gdy element referencyjny jest zagnieżdżony w innych, co może mieć miejsce przy absolutnym pozycjonowaniu. Oto rozwiązanie tego scenariusza:

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
Nie sądzę, żeby uwzględniało htmlprzesunięcie elementu
— apieceofbart

3
Działa świetnie z przewijania pojemników, tylko z niewielkimi zmianami zamienić while(reference !== undefined)z while(reference). W Chrome przynajmniej offsetParent nie jest undefined, ale null. Samo sprawdzenie, czy referencejest prawdą, zapewni, że będzie działać zarówno z, jak undefinedi z null.
— blex

Dałbym kolejne +1, gdybym mógł, z powodu poinformowania mnie o istnieniu offsetParentnieruchomości, która okazuje się bardzo przydatna również w innych sytuacjach!
— FonzTech,

Ogólnie rzecz biorąc, sprawdzanie przed niezdefiniowanym jest zwykle złym pomysłem
— Juan Mendes

Myślę, że musisz odjąć scrollLefti scrollTopzrekompensować przewijanych potomków.
— Robert

20

Dobry opis trudności tego problemu można znaleźć tutaj: http://www.quirksmode.org/js/events_properties.html#position

Korzystając z opisanej tam techniki, możesz znaleźć pozycję myszy w dokumencie. Wtedy po prostu sprawdzić, czy to wewnątrz obwiedni swojego elementu, który można znaleźć dzwoniąc element.getBoundingClientRect()która zwróci obiekt o następujących właściwościach: { bottom, height, left, right, top, width }. Stamtąd nie jest łatwo ustalić, czy zdarzyło się nawet w twoim żywiole, czy nie.


1
Niestety nie udaje się to, jeśli zachodzi jakakolwiek rotacja
— Eric

17

Wypróbowałem wszystkie te rozwiązania i ze względu na moją specjalną konfigurację z transformowanym matrycowo kontenerem (biblioteka panzoom) żadne nie działało. Zwraca prawidłową wartość, nawet jeśli jest powiększona i przeskalowana:

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

Ale tylko wtedy, gdy nie ma na niej elementów potomnych. Można to obejść, czyniąc je „niewidocznymi” dla wydarzenia, używając CSS:

.child {
   pointer-events: none;
}

3
Jest to zdecydowanie sposób na zrobienie tego w 2019 r. Pozostałe odpowiedzi są pełne starego, chrupiącego bagażu.
— Colin D

1
@ColinD dziękuję! Zapomniałem dodać, że działa to również w IE11.
— Fabian von Ellerts

To zadziałało dla mnie. Jestem jednak podejrzliwy, że 1) kilka pozytywnych opinii 2) wyżej ocenione odpowiedzi są znacznie bardziej skomplikowane i 3) nie widzę żadnych wad. Czy ktoś zna jakąkolwiek wadę korzystania z tego podejścia?
— Mark E

1
@MarkE Nie ma w tym nic podejrzanego. To jedna z wielu wad StackOverflow. Te odpowiedzi, które widzisz na górze, zostały opublikowane wiele lat przed odpowiedzią tutaj, dzięki czemu zyskały ogromny rozmach w głosowaniu. Gdy odpowiedź nabierze tempa, trudno jest ją pokonać.
— Jack Giffin

9

Natknąłem się na to pytanie, ale aby to zadziałało w moim przypadku (używając przeciągania na elemencie DOM (nie jest to płótno w moim przypadku)), stwierdziłem, że musisz tylko użyć offsetXi offsetYzdarzenia przeciągania myszą .

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

2
to zadziałało dla mnie świetnie. dlaczego nikt tego nie głosował? Zastanawiam się, czy są jakieś pułapki. Jeśli coś znajdę, zdam raport!
— labraks

7
event.offsetX jest związany z elementem, nad którym aktualnie znajduje się wskaźnik myszy, a nie z elementem, do którego jest dołączony detektor przeciągania. Jeśli nie masz struktury zagnieżdżonej, jest to w porządku, ale jeśli tak, to nie zadziała.
— opsb

7

Daję +1 od odpowiedzi Marka van Wyk, która poprowadziła mnie we właściwym kierunku, ale nie do końca mnie rozwiązała. Nadal miałem przesunięcie w malowaniu w elementach zawartych w innym elemencie.

FOllowing rozwiązało to dla mnie:

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

Innymi słowy - po prostu ułożyłem wszystkie odsunięcia od wszystkich zagnieżdżonych elementów


+1 dla Ciebie! Oto odpowiedź, której szukałem. Miałem dwa płótna ułożone jeden na drugim, a współrzędne były błędne z powodu innych div. Wiedziałem, że to jest problem, ale nie znałem logiki / równania, aby to zrekompensować. Właśnie rozwiązałeś mój problem! = D dzięki!
— Partack

5

Żadna z powyższych odpowiedzi nie jest zadowalająca IMO, więc oto, czego używam:

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

A jeśli kiedykolwiek będziesz potrzebować znać aktualną pozycję przewijania strony Y:

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

4

Ci z was, którzy opracowują zwykłe strony internetowe lub PWA (progresywne aplikacje internetowe) dla urządzeń mobilnych i / lub laptopów / monitorów z ekranami dotykowymi, wylądowali tutaj, ponieważ mogą być przyzwyczajeni do obsługi zdarzeń myszy i są nowi w niekiedy bolesnych doświadczeniach dotyku wydarzenia ... tak!

Istnieją tylko 3 zasady:

  1. Rób jak najmniej podczas imprez mousemovelub touchmovewydarzeń.
  2. Zrobić jak najwięcej w trakcie mousedownlub touchstartwydarzenia.
  3. Anuluj propagację i zapobiegaj ustawieniom domyślnym zdarzeń dotykowych, aby zapobiec uruchamianiu się zdarzeń myszy na urządzeniach hybrydowych.

Nie trzeba dodawać, że touchzdarzenia są bardziej skomplikowane w związku ze zdarzeniami, ponieważ może być ich więcej niż jeden i są bardziej elastyczne (skomplikowane) niż zdarzenia myszy. Omówię tutaj tylko jeden dotyk. Tak, jestem leniwy, ale to najczęstszy rodzaj dotyku, więc proszę.

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.

Wolisz używać Vue.js ? Ja robię! Wtedy twój HTML wyglądałby tak:

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

3

możesz to zdobyć

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

Czy to zadziała w IE, czy IE nadal używa window.event zamiast przekazywać zdarzenie do pierwszego argumentu detektora? edycja - Wydaje mi się, że IE i tak nie ma elementu canvas do wersji 9, ale to prawdopodobnie powinno wspierać IE z powodu takich rzeczy jak excanvas ....
— Dagg Nabbit

21
To da współrzędne w stosunku do okna przeglądarki, nadal musisz dowiedzieć się, czy są one w elemencie za pomocą elementu.getBoundingClientRect ()
— David W. Keith

dziękuję za poinformowanie mnie o getBoundingClientRect !!!! Nigdy nie zdawałem sobie sprawy, że coś takiego istnieje!
— Gershom

@ DavidW.Keith komentarz powinien być naprawdę uważany za prawidłową odpowiedź!
— Ulrik. S

3

Zaczerpnięte z tego samouczka , z poprawkami wprowadzonymi dzięki pierwszemu komentarzowi:

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

Użyj na płótnie w następujący sposób:

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

3

Zdaję sobie sprawę, że jestem trochę spóźniony, ale działa to z javascript PURE, a nawet daje współrzędne wskaźnika w elemencie, jeśli element jest większy niż rzutnia, a użytkownik przewinął.

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

Jak to działa.

Pierwszą rzeczą, którą robimy, jest uzyskanie położenia elementu HTML (obszaru zawartości) względem bieżącej rzutni. Jeśli strona ma paski przewijania i jest przewijana, wówczas liczba zwrócona przez getBoundingClientRect().leftznacznik html będzie ujemna. Następnie używamy tej liczby do obliczenia odległości między elementem a lewą stroną obszaru treści. Zelement_offset_x = element.getBoundingClientRect().left......;

Znając odległość elementu od obszaru zawartości. event.clientXdaje nam odległość wskaźnika od rzutni. Ważne jest, aby zrozumieć, że rzutnia i obszar zawartości to dwa różne elementy, rzutnia może się przesuwać, jeśli strona jest przewijana. Dlatego ClientX zwróci SAMY numer, nawet jeśli strona zostanie przewinięta.

Aby to zrekompensować, musimy dodać pozycję x wskaźnika (względem rzutni), do pozycji x rzutni (względem obszaru zawartości). Pozycja X rzutni znajduje się za pomocą window.pageXOffset.


1
Dziękujemy za to, że jesteś jedyną osobą odpowiedzialną za przewijanie. Rozważ zmianę odpowiedzi, aby dodać również oś Y.
— frabjous

3

W oparciu o rozwiązanie @ Spider moja wersja inna niż JQuery jest następująca:

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

Działa to zarówno z przewijaniem, jak i powiększaniem (w takim przypadku czasami zwraca liczby zmiennoprzecinkowe).


Głosowałbym za tym, ale czy nie powinny to być znaki minus przesunięcia strony? Albo to, albo nawiasy wokół drugiej części?
— Chris Sunami wspiera Monikę

1

Współrzędne myszy w obszarze roboczym można uzyskać dzięki event.offsetX i event.offsetY. Oto mały fragment, który potwierdza mój punkt widzenia:

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>
    


Nie działa, jeśli inny div nakłada się na płótno, tak jak powiedział @opsb
— 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)
}

HTMLElement.offsetLeft

Właściwość HTMLElement.offsetLefttylko do odczytu zwraca liczbę pikseli, o jaką lewy górny róg bieżącego elementu jest przesunięty w lewo w ciąguHTMLElement.offsetParent węźle.

Dla elementów blokowych, offsetTop, offsetLeft, offsetWidthi offsetHeightopisuje okno graniczną elementu w stosunku do offsetParent.

Jednakże, w przypadku elementów inline (na przykład span), które owijają się od jednej linii do następnej, offsetTopi offsetLeftopisują położenie pierwsze pole pogranicza (stosowanie Element.getClientRects()aby jej szerokość i wysokość), natomiast offsetWidtha offsetHeightopisują wymiarów pudełka obwiednię (użyj, Element.getBoundingClientRect()aby uzyskać jego pozycję). Dlatego pole do lewej, do góry, szerokości i wysokości offsetLeft, offsetTop, offsetWidthi offsetHeightnie będzie obwiednie o rozpiętości z owiniętego tekstu.

HTMLElement.offsetTop

Właściwość HTMLElement.offsetToptylko do odczytu zwraca odległość bieżącego elementu w stosunku do szczytu offsetParentwęzła.

MouseEvent.pageX

Właściwość pageXtylko do odczytu zwraca współrzędną X (poziomą) w pikselach zdarzenia w stosunku do całego dokumentu. Ta właściwość uwzględnia przewijanie strony w poziomie.

MouseEvent.pageY

Właściwość MouseEvent.pageYtylko do odczytu zwraca współrzędną Y (pionową) w pikselach zdarzenia w stosunku do całego dokumentu. Ta właściwość uwzględnia wszelkie pionowe przewijanie strony.

W celu uzyskania dalszych wyjaśnień zobacz 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


Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie dla czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu.
— Patrick Hund,

Naprawdę mam nadzieję, że czytelnicy w przyszłości będą mieli API JS, które to dla nich oblicza. ;-) Jest to prawdopodobnie najprostsza, pełna, samodzielna odpowiedź. Komentowanie zrozumiałego kodu jest tylko rozpraszaniem odpadów.
— lama12345,

Popieram prośbę @ PatrickHund o wyjaśnienie. Nie jestem CSS / JS ekspert i wiedząc więcej o relacjach między, na przykład, pagei offsetbyłoby bardzo pomocne dla mnie. Dziękujemy za rozpatrzenie tej prośby!
— cxw

@ cxw Ok, jesteś teraz 2. oceną negatywną (miałem 1 opinię) ... Dodałem teraz długie wyjaśnienie, jest to 10 razy więcej niż 4 linie kodu. Zapraszamy do lektury. Rozważyłem twoją prośbę! : p
— lama12345

1
@cxw Pomyślałem, dodając dodatkowy element pozycjonowany bezwzględnie i zmuszając sam element canvas również poza ekranem, więc musiałem przewinąć do niego, jak lewy / górny 2000px poza ekranem. Nie można zmusić tego kodu do złamania.
— lama12345

1

Wdrożyłem inne rozwiązanie, które moim zdaniem jest bardzo proste, więc pomyślałem, że podzielę się z wami.

Problemem było dla mnie to, że przeciągnięty div przeskoczyłby do 0,0 dla kursora myszy. Musiałem więc uchwycić pozycję myszy na div, aby dostosować nową pozycję div.

Przeczytałem div div PageX i PageY i ustawiłem odpowiednio górną i lewą stronę, a następnie, aby uzyskać wartości do dostosowania współrzędnych, aby utrzymać kursor w początkowej pozycji w div, używam detektora onDragStart i przechowuję e.nativeEvent .layerX i e.nativeEvent.layerY, które tylko w początkowym spuście dają pozycję myszy w przeciąganym div.

Przykładowy kod:

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

Mam nadzieję, że pomoże to komuś, kto przeszedł te same problemy, przez które przeszedłem :)


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

to działa ok!


0

Musisz znać strukturę swojej strony, ponieważ jeśli twoje płótno jest dzieckiem div, który z kolei jest dzieckiem innego diva ... historia staje się bardziej skomplikowana. Oto mój kod dla obszaru roboczego, który znajduje się w 2 poziomach 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);

});


0

Oryginalna odpowiedź mówi, by umieścić ją w ramce iframe. Lepszym rozwiązaniem jest użycie zdarzeń offsetX i offsetY na kanwie, której wypełnienie jest ustawione na 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

Oto co mam.

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

    var posx = 0;
    var posy = 0;

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

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

0

Można skorzystać getBoudingClientRect()z relativerodzicem.

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)
})
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.