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.

Ben Shelock
źródło
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 () .

Sparkyspider
źródło
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

dowolny kod
źródło
2
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.

LindaQ
źródło
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,
  }; 

}
Atrahasis
źródło
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.

David W. Keith
źródło
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;
}
Fabian von Ellerts
źródło
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;
}
Jan
źródło
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

Matt
źródło
+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
Florian B.
źródło
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">
John T.
źródło
3

możesz to zdobyć

var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
    var xCoor = e.clientX;
    var yCoor = e.clientY;
}
rob waminal
źródło
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 );
} );
Jonathan H.
źródło
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.

FutureSci
źródło
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).

Letokteren
źródło
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>
    

Nino Filiu
źródło
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

lama12345
źródło
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 :)

Athinodoros Sgouromallis
źródło
1
function myFunction(e) {
    var x =  e.clientX - e.currentTarget.offsetLeft ; 
    var y = e.clientY - e.currentTarget.offsetTop ;
}

to działa ok!

M9J_cfALt
źródło
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);

});

Eli Mashiah
źródło
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>
Smertrios2007
źródło
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);
});
Shmoo
źródło
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)
})
BrieucKyo
źródło