Chcę zrobić małą aplikację do malowania z płótna. Muszę więc znaleźć pozycję myszy na płótnie.
javascript
Ben Shelock
źródło
źródło
Odpowiedzi:
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.
Jeśli próbujesz ustawić pozycję myszy na stronie w przewijanym panelu:
Lub pozycja względem strony:
Zwróć uwagę na następującą optymalizację wydajności:
W ten sposób JQuery nie musi szukać
#element
każdej linii.Aktualizacja
Poniżej znajduje się nowsza wersja, tylko JavaScript, autorstwa @anytimecoder dla przeglądarek obsługujących getBoundingClientRect () .
źródło
var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();
dovar y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Ponieważ nie znalazłem odpowiedzi bez jQuery, którą można skopiować / wkleić, oto rozwiązanie, którego użyłem:
JSFiddle pełnego przykładu
źródło
e.currentTarget
, a nie e.target. W przeciwnym razie wpłyną na to elementy potomnePoniższe oblicza relację położenia myszy do elementu canvas:
W tym przykładzie
this
odnosi się doexample
elementu ie
jestonmousemove
zdarzeniem.źródło
var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
this
nae.currentTarget
, dzięki czemu uzyskasz pozycję względem elementu, do którego dodano detektor zdarzeń.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:
źródło
html
przesunięcie elementuwhile(reference !== undefined)
zwhile(reference)
. W Chrome przynajmniej offsetParent nie jestundefined
, alenull
. Samo sprawdzenie, czyreference
jest prawdą, zapewni, że będzie działać zarówno z, jakundefined
i znull
.offsetParent
nieruchomości, która okazuje się bardzo przydatna również w innych sytuacjach!scrollLeft
iscrollTop
zrekompensować przewijanych potomków.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.źródło
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:
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:
źródło
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ć
offsetX
ioffsetY
zdarzenia przeciągania myszą .źródło
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:
Innymi słowy - po prostu ułożyłem wszystkie odsunięcia od wszystkich zagnieżdżonych elementów
źródło
Żadna z powyższych odpowiedzi nie jest zadowalająca IMO, więc oto, czego używam:
A jeśli kiedykolwiek będziesz potrzebować znać aktualną pozycję przewijania strony Y:
źródło
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:
mousemove
lubtouchmove
wydarzeń.mousedown
lubtouchstart
wydarzenia.Nie trzeba dodawać, że
touch
zdarzenia 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ę.Wolisz używać Vue.js ? Ja robię! Wtedy twój HTML wyglądałby tak:
źródło
możesz to zdobyć
źródło
Zaczerpnięte z tego samouczka , z poprawkami wprowadzonymi dzięki pierwszemu komentarzowi:
Użyj na płótnie w następujący sposób:
źródło
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ął.
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().left
znacznik 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.clientX
daje 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.
źródło
W oparciu o rozwiązanie @ Spider moja wersja inna niż JQuery jest następująca:
Działa to zarówno z przewijaniem, jak i powiększaniem (w takim przypadku czasami zwraca liczby zmiennoprzecinkowe).
źródło
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:
źródło
HTMLElement.offsetLeft
Właściwość
HTMLElement.offsetLeft
tylko 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
,offsetWidth
ioffsetHeight
opisuje okno graniczną elementu w stosunku dooffsetParent
.Jednakże, w przypadku elementów inline (na przykład
span
), które owijają się od jednej linii do następnej,offsetTop
ioffsetLeft
opisują położenie pierwsze pole pogranicza (stosowanieElement.getClientRects()
aby jej szerokość i wysokość), natomiastoffsetWidth
aoffsetHeight
opisują wymiarów pudełka obwiednię (użyj,Element.getBoundingClientRect()
aby uzyskać jego pozycję). Dlatego pole do lewej, do góry, szerokości i wysokościoffsetLeft
,offsetTop
,offsetWidth
ioffsetHeight
nie będzie obwiednie o rozpiętości z owiniętego tekstu.HTMLElement.offsetTop
Właściwość
HTMLElement.offsetTop
tylko do odczytu zwraca odległość bieżącego elementu w stosunku do szczytuoffsetParent
węzła.MouseEvent.pageX
Właściwość
pageX
tylko 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.pageY
tylko 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
źródło
page
ioffset
byłoby bardzo pomocne dla mnie. Dziękujemy za rozpatrzenie tej prośby!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:
Mam nadzieję, że pomoże to komuś, kto przeszedł te same problemy, przez które przeszedłem :)
źródło
to działa ok!
źródło
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:
});
źródło
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.
źródło
Oto co mam.
źródło
Można skorzystać
getBoudingClientRect()
zrelative
rodzicem.źródło