Temukan posisi mouse relatif terhadap elemen

244

Saya ingin membuat aplikasi melukis kecil menggunakan kanvas. Jadi saya perlu menemukan posisi mouse di atas kanvas.

Ben Shelock
sumber
2
Solusi lengkap: acko.net/blog/…
edA-qa mort-ora-y
3
Saya suka betapa singkatnya, tetapi menjelaskan semua posting ini.
dwjohnston
Ini benar-benar tua, tetapi saya baru saja memulai proyek GitHub yang, antara lain, melakukan apa yang Anda butuhkan: brainlessdeveloper.com/mouse-move-interaction-spot-js
Fausto NA

Jawaban:

177

Untuk orang yang menggunakan JQuery:

Terkadang, ketika Anda memiliki elemen bersarang, salah satunya dengan peristiwa yang menyertainya, bisa membingungkan untuk memahami apa yang dilihat browser Anda sebagai induknya. Di sini, Anda dapat menentukan induk yang mana.

Anda mengambil posisi mouse, dan kemudian kurangi dari posisi offset elemen induk.

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

Jika Anda mencoba untuk mendapatkan posisi mouse pada halaman di dalam panel gulir:

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

Atau posisi relatif ke halaman:

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

Perhatikan pengoptimalan kinerja berikut:

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

Dengan cara ini, JQuery tidak harus mencari #elementsetiap baris.

Memperbarui

Ada versi yang lebih baru, khusus JavaScript di bawah ini oleh @anytimecoder di bawah ini untuk peramban yang mendukung getBoundingClientRect () .

sparkyspider
sumber
7
Apakah itu berhasil untuk Anda @ben, saya akan menghargai "Jawaban yang Benar" atau komentar tentang apa yang masih tidak berhasil untuk Anda. Mungkin saya bisa membantu lebih jauh.
sparkyspider
8
Sebaiknya hindari menggunakan $ ('selector') dalam event handler, kecuali Anda menginginkan kode yang sangat lamban. Pra-pilih elemen Anda, dan gunakan referensi yang dipilih sebelumnya di handler Anda. Sama dengan $ (window) lakukan itu sekali dan cache itu.
Austin France
2
ini bukan menyebutkan diperlukan: jika Anda menyalin menyisipkan kode di atas, ingat untuk memperbaiki var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();kevar y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Raj Nathani
77
Bagaimana itu bisa menjadi jawaban karena pertanyaan itu tidak ada hubungannya dengan jQuery?
FlorianB
2
@ Black, tetapi beberapa orang menanyakan hal-hal dalam javascript alih-alih jquery karena jquery mungkin tidak kompatibel di lingkungan mereka.
dbrree
307

Karena saya tidak menemukan jawaban bebas jQuery yang dapat saya salin / tempel, inilah solusi yang saya gunakan:

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 dari contoh lengkap

anytimecoder
sumber
2
Anda harus membulatkan batas pembatas untuk memastikan nilai integer dengan metode ini.
Jake Cobb
2
Hasil edit baru harus memperbaiki masalah pengguliran (menggunakan clientX / Y)
Erik Koopmans
6
Jawaban ini harus dipilih. Terima kasih anytimecoder dan @ErikKoopmans.
Ivan
3
PSA: Komentar @mpen sudah usang; metode ini TIDAK berfungsi, bahkan dalam kasus pengguliran. Lihat versi terbaru dari Fiddle mereka: jsfiddle.net/6wcsovp2
Xharlie
4
Terima kasih! Satu catatan: Anda perlu e.currentTarget, bukan e.target. Jika tidak, elemen anak-anak akan mempengaruhinya
Maxim Georgievskiy
60

Yang berikut ini menghitung relasi posisi mouse ke elemen kanvas:

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

Dalam contoh ini, thismengacu pada exampleelemen, dan eadalah onmousemoveacara.

LindaQ
sumber
83
Mungkin saya tetapi dua baris kode yang menggunakan kata kunci "ini" tidak memiliki konteks?
Deratrius
9
Konteks yang jelas kurang. 'e' adalah acara dan 'ini' adalah elemen acara terkait var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
Nick Bisby
22
Ini tidak berfungsi jika beberapa elemen turunan menggunakan posisi relatif atau absolut.
edA-qa mort-ora-y
12
Anda dapat beralih thiske e.currentTarget, yang akan membuat Anda posisi relatif terhadap elemen yang Anda tambahkan pendengar acara.
Linus Unnebäck
2
Hal ini tampaknya memberikan relatve posisi ke terlihat bagian dari elemen, tidak seluruh elemen. Apakah ada cara untuk mengakomodasi itu jika bagian dari elemen tidak dapat dilihat di viewport dan ada scrollbar, dll?
frabjous
37

Tidak ada jawaban di javascript murni yang mengembalikan koordinat relatif ketika elemen referensi bersarang di dalam orang lain yang dapat dengan posisi absolut. Berikut ini solusi untuk skenario ini:

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
sumber
3
Saya tidak berpikir itu memperhitungkan htmlelemen akun diimbangi
masing
3
Bekerja sangat baik dengan wadah bergulir, hanya dengan sedikit perubahan: ganti while(reference !== undefined)dengan while(reference). Setidaknya di Chrome, offsetParent tidak berakhir undefined, tetapi null. Hanya memeriksa apakah referencekebenaran akan memastikan itu berfungsi dengan baik undefineddan null.
blex
Saya akan memberi +1 lainnya jika saya bisa, karena memberi tahu saya ada offsetParentproperti, yang ternyata sangat berguna dalam situasi lain!
FonzTech
Secara umum, memeriksa terhadap yang tidak terdefinisi biasanya merupakan ide yang buruk
Juan Mendes
Saya pikir Anda perlu mengurangi scrollLeftdan scrollTopmengkompensasi keturunan yang digulir.
Robert
20

Tulisan yang bagus tentang kesulitan masalah ini dapat ditemukan di sini: http://www.quirksmode.org/js/events_properties.html#position

Dengan menggunakan teknik yang dijelaskan di sana Anda dapat menemukan posisi mouse dalam dokumen. Kemudian Anda hanya memeriksa untuk melihat apakah di dalam kotak berlari dari elemen Anda, yang dapat Anda temukan dengan panggilan element.getBoundingClientRect()yang akan mengembalikan objek dengan properti berikut: { bottom, height, left, right, top, width }. Dari sana sepele untuk mencari tahu apakah peristiwa itu terjadi di dalam elemen Anda atau tidak.

David W. Keith
sumber
1
Sayangnya, ini gagal jika ada rotasi yang sedang terjadi
Eric
17

Saya mencoba semua solusi ini dan karena pengaturan khusus saya dengan wadah yang diubah matriks (perpustakaan panzoom) tidak ada yang berhasil. Ini mengembalikan nilai yang benar, bahkan jika diperbesar dan digeser:

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

Tetapi hanya jika tidak ada elemen anak di jalan. Ini dapat dielakkan dengan membuatnya 'tidak terlihat' pada acara tersebut, menggunakan CSS:

.child {
   pointer-events: none;
}
Fabian von Ellerts
sumber
3
Ini jelas merupakan cara untuk melakukan ini pada tahun 2019. Jawaban-jawaban lainnya dipenuhi dengan bagasi crufty tua.
Colin D
1
@ColinD terima kasih! Saya lupa menambahkan bahwa ini juga berfungsi di IE11.
Fabian von Ellerts
Ini berhasil untuk saya. Namun, saya curiga bahwa 1) Sedikit upvotes 2) jawaban berperingkat lebih tinggi jauh lebih rumit dan 3) Saya tidak melihat ada kekurangan yang dijelaskan. Adakah yang tahu tipuan menggunakan pendekatan ini?
Mark E
1
@ Marke Tidak ada yang mencurigakan tentang itu. Itu salah satu dari banyak kesalahan StackOverflow. Jawaban yang Anda lihat di atas diposkan bertahun-tahun sebelum jawaban ini di sini, sehingga mereka mendapatkan momentum suara yang luar biasa. Setelah jawaban mendapatkan momentum ini, cukup sulit dan sangat jarang untuk mengalahkannya.
Jack Giffin
9

Saya menemukan pertanyaan ini, tetapi untuk membuatnya berfungsi untuk kasus saya (menggunakan dragover pada elemen DOM (tidak menjadi kanvas dalam kasus saya)), saya menemukan bahwa Anda hanya perlu menggunakan offsetXdan offsetYpada acara dragover-mouse .

onDragOver(event){
 var x = event.offsetX;
 var y = event.offsetY;
}
John
sumber
2
ini bekerja baik untuk saya. mengapa tidak ada yang membatalkan ini? Saya ingin tahu apakah ada jebakan. Jika saya menemukan, saya akan melaporkan kembali!
seabass
7
event.offsetX relatif terhadap elemen yang pointer mouse saat ini berakhir, bukan elemen yang memiliki pendengar dragover yang melekat padanya. Jika Anda tidak memiliki struktur elemen bersarang maka ini baik-baik saja, tetapi jika Anda melakukannya maka ini tidak akan berhasil.
opsb
7

Saya memberi +1 jawaban Mark van Wyk karena membuat saya berada di arah yang benar, tetapi tidak cukup menyelesaikannya untuk saya. Saya masih memiliki offset pada lukisan dalam elemen-elemen yang terdapat dalam elemen lain.

Bagaimana memecahkannya untuk saya:

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

Dengan kata lain - saya hanya menumpuk semua offset dari semua elemen yang bersarang

Mat
sumber
+1 untuk Anda! Inilah jawaban yang saya cari. Saya memiliki dua kanvas ditumpuk di atas satu sama lain dan koordinat semua salah karena div lainnya. Saya tahu ini masalahnya, tetapi tidak tahu logika / persamaan untuk menggantinya. Anda baru saja memperbaiki masalah saya juga! = D terima kasih!
Partack
5

Tidak ada jawaban di atas yang IMO memuaskan, jadi inilah yang saya gunakan:

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

Dan jika Anda perlu mengetahui posisi gulir Y saat ini dari halaman:

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

Bagi Anda yang mengembangkan situs web biasa atau PWA (Progressive Web Apps) untuk perangkat seluler dan / atau laptop / monitor dengan layar sentuh, maka Anda telah mendarat di sini karena Anda mungkin terbiasa dengan acara tetikus dan baru dalam pengalaman Touch yang terkadang menyakitkan. acara ... yay!

Hanya ada 3 aturan:

  1. Lakukan sesedikit mungkin selama mousemove atau touchmoveacara.
  2. Lakukan sebanyak mungkin selama mousedown atau touchstartacara.
  3. Batalkan propagasi dan cegah default untuk acara sentuh untuk mencegah acara mouse agar tidak juga menembaki perangkat hybrid.

Tak perlu dikatakan, hal-hal lebih rumit dengan touchperistiwa karena bisa ada lebih dari satu dan mereka lebih fleksibel (rumit) daripada peristiwa mouse. Saya hanya akan membahas satu sentuhan di sini. Ya, saya malas, tapi itu jenis sentuhan yang paling umum, jadi itulah.

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.

Lebih suka menggunakan Vue.js ? Saya lakukan! Maka HTML Anda akan terlihat seperti ini:

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

Anda bisa mendapatkannya dengan

var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
    var xCoor = e.clientX;
    var yCoor = e.clientY;
}
merampok waminal
sumber
Apakah ini akan berfungsi di IE, atau apakah IE masih menggunakan window.event bukannya meneruskan acara ke argumen pertama dari pendengar? sunting - Saya kira IE tidak memiliki elemen kanvas sampai versi 9, tetapi ini mungkin masih mendukung IE karena hal-hal seperti excanvas ....
Dagg Nabbit
21
Ini akan memberikan koordinat relatif ke jendela browser, masih perlu mencari tahu apakah mereka berada di dalam elemen menggunakan element.getBoundingClientRect ()
David W. Keith
terima kasih telah membuat saya sadar akan getBoundingClientRect !!!! Saya tidak pernah menyadari ada hal seperti itu!
Gershom
@ DavidW.Keith komentar harus benar-benar dianggap sebagai jawaban yang benar!
Ulrik. S
3

Diambil dari tutorial ini , dengan koreksi dilakukan berkat komentar teratas:

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

Gunakan pada kanvas sebagai berikut:

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

Saya sadar saya sedikit terlambat, tetapi ini bekerja dengan javascript PURE, dan bahkan memberi Anda koordinat pointer dalam elemen jika elemen lebih besar dari viewport dan pengguna telah menggulir.

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

Bagaimana itu bekerja.

Hal pertama yang kami lakukan adalah mendapatkan lokasi elemen HTML (area konten) relatif terhadap viewport saat ini. Jika halaman tersebut memiliki scrollbar dan digulir, maka nomor tersebut dikembalikan olehgetBoundingClientRect().left untuk tag html akan negatif. Kami kemudian menggunakan nomor ini untuk menghitung jarak antara elemen dan kiri area konten. Denganelement_offset_x = element.getBoundingClientRect().left......;

Mengetahui jarak elemen dari area konten. event.clientXmemberi kita jarak pointer dari viewport. Penting untuk dipahami bahwa viewport dan area konten adalah dua entitas yang berbeda, viewport dapat bergerak jika halaman tersebut digulir. Oleh karena itu, clientX akan mengembalikan nomor SAMA meskipun halaman tersebut digulir.

Untuk mengimbangi ini, kita perlu menambahkan posisi x dari pointer (relatif ke viewport), ke posisi x viewport (relatif terhadap area konten). Posisi X viewport ditemukan dengan window.pageXOffset.

FutureSci
sumber
1
Terima kasih telah menjadi satu-satunya penjawab untuk berpikir tentang menggulir. Pertimbangkan untuk mengubah jawaban Anda untuk menambahkan sumbu y juga.
frabjous
3

Berdasarkan solusi @ Spider, versi non JQuery saya adalah ini:

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

Ini berfungsi baik dengan menggulir dan memperbesar (dalam hal ini kadang-kadang mengembalikan mengapung).

Letokteren
sumber
Saya akan melakukan upvote, tetapi bukankah itu merupakan tanda minus untuk offset halaman? Entah itu, atau tanda kurung di sekitar bagian kedua?
Chris Sunami mendukung Monica
1

Koordinat mouse di dalam kanvas dapat diperoleh berkat event.offsetX dan event.offsetY. Berikut cuplikan kecil untuk membuktikan pendapat saya:

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
sumber
Tidak berfungsi jika div lain overlay kanvas, seperti kata @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

Properti HTMLElement.offsetLeftbaca-saja mengembalikan jumlah piksel yang sudut kiri atas elemen saat ini diimbangi ke kiri dalamHTMLElement.offsetParent node.

Untuk unsur blok-tingkat, offsetTop, offsetLeft, offsetWidth, dan offsetHeightmenggambarkan kotak perbatasan elemen relatif terhadap offsetParent.

Namun, untuk elemen level-inline (seperti span) yang dapat membungkus dari satu baris ke baris berikutnya, offsetTopdan offsetLeftmenggambarkan posisi kotak batas pertama (gunakan Element.getClientRects()untuk mendapatkan lebar dan tinggi), sementara offsetWidthdan offsetHeightmenggambarkan dimensi kotak batas pembatas (gunakan Element.getBoundingClientRect()untuk mendapatkan posisinya). Oleh karena itu, sebuah kotak dengan kiri, atas, lebar dan tinggi offsetLeft, offsetTop, offsetWidthdan offsetHeighttidak akan menjadi kotak berlari untuk rentang dengan teks dibungkus.

HTMLElement.offsetTop

Properti HTMLElement.offsetTopread-only mengembalikan jarak elemen saat ini relatif ke atas offsetParentnode.

MouseEvent.pageX

Properti pageXbaca-saja mengembalikan koordinat X (horizontal) dalam piksel acara relatif ke seluruh dokumen. Properti ini memperhitungkan setiap pengguliran horizontal halaman.

MouseEvent.pageY

Properti MouseEvent.pageYbaca-saja mengembalikan koordinat Y (vertikal) dalam piksel acara relatif ke seluruh dokumen. Properti ini memperhitungkan setiap pengguliran vertikal halaman.

Untuk penjelasan lebih lanjut, silakan lihat Jaringan Pengembang 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/HTMLElement/offsetLeft https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop

lama12345
sumber
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda.
Patrick Hund
Saya sangat berharap pembaca di masa depan memiliki API JS yang menghitung ini untuk mereka. ;-) Ini mungkin jawaban yang paling sederhana, lengkap, mandiri. Mengomentari kode penjelasan sendiri hanya mengganggu limbah.
lama12345
Saya minta @ PatrickHund meminta penjelasan. Saya bukan ahli CSS / JS, dan mengetahui lebih banyak tentang hubungan antara, misalnya, pagedan offsetakan sangat membantu saya. Terima kasih telah mempertimbangkan permintaan ini!
cxw
@cxw Ok, Anda adalah downvote ke-2 sekarang (punya 1 upvote) ... Saya menambahkan penjelasan panjang sekarang, itu seperti 10x selama 4 baris kode. Selamat datang, selamat membaca. Saya mempertimbangkan permintaan Anda! : p
lama12345
1
@ cxw Saya main-main dengan menambahkan elemen posisi absolut ekstra dan memaksa elemen kanvas itu sendiri offscreen juga, jadi saya harus gulir ke sana, seperti kiri / atas 2000px offscreen. Tidak dapat memecahkan kode ini.
lama12345
1

Saya menerapkan solusi lain yang saya pikir sangat sederhana, jadi saya pikir saya akan berbagi dengan kalian.

Jadi, masalah bagi saya adalah bahwa div yang diseret akan melompat ke 0,0 untuk kursor mouse. Jadi saya perlu menangkap posisi mouse pada div untuk menyesuaikan posisi divs baru.

Saya membaca div PageX dan PageY dan mengatur bagian atas dan kiri sesuai dengan itu dan kemudian untuk mendapatkan nilai-nilai untuk menyesuaikan koordinat untuk menjaga kursor pada posisi awal di div saya menggunakan pendengar onDragStart dan menyimpan e.nativeEvent .layerX dan e.nativeEvent.layerY yang hanya di trigger awal memberi Anda posisi mouse di dalam div yang dapat ditarik.

Kode contoh:

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

Saya harap ini akan membantu seseorang yang mengalami masalah yang sama seperti yang saya alami :)

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

ini berfungsi ok!

M9J_cfALt
sumber
0

Anda harus mengetahui struktur halaman Anda, karena jika kanvas Anda adalah anak dari div yang pada gilirannya adalah anak dari div lain ... maka ceritanya menjadi lebih rumit. Inilah kode saya untuk kanvas yang ada di dalam 2 level 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
sumber
0

Jawaban orisinal mengatakan untuk meletakkannya di iframe. Solusi yang lebih baik adalah dengan menggunakan peristiwa offsetX dan offsetY pada kanvas yang memiliki padding set ke 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
sumber
0

Inilah yang saya dapat.

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

    var posx = 0;
    var posy = 0;

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

    alert(posx);
    alert(posy);
});
Sial
sumber
0

Anda dapat menggunakan getBoudingClientRect()orang relativetua.

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
sumber