Tuval kullanarak küçük bir resim uygulaması yapmak istiyorum. Bu yüzden farenin tuval üzerindeki konumunu bulmam gerekiyor.
Tuval kullanarak küçük bir resim uygulaması yapmak istiyorum. Bu yüzden farenin tuval üzerindeki konumunu bulmam gerekiyor.
Yanıtlar:
JQuery kullanan kişiler için:
Bazen, bunlardan biri etkinliğe eklenmiş olan iç içe geçmiş öğeleriniz olduğunda, tarayıcınızın üst öğe olarak gördüklerini anlamak kafa karıştırıcı olabilir. Burada hangi ebeveyni belirtebilirsiniz.
Fare konumunu alır ve daha sonra üst öğenin ofset konumundan çıkarırsınız.
var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;
Fare konumunu kaydırma bölmesinin içindeki bir sayfada almaya çalışıyorsanız:
var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();
Veya sayfaya göre konum:
var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Aşağıdaki performans optimizasyonuna dikkat edin:
var offset = $('#element').offset();
// Then refer to
var x = evt.pageX - offset.left;
Bu şekilde, JQuery'nin #element
her satır için arama yapması gerekmez .
GetBoundingClientRect () 'i destekleyen tarayıcılar için aşağıdaki @ anytimecoder tarafından daha yeni, yalnızca JavaScript içeren bir sürüm var .
var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();
içinvar y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Kopyalayabildiğim / yapıştırabildiğim jQuery içermeyen bir cevap bulamadığım için, kullandığım çözüm:
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.
}
e.currentTarget
e.target değil, ihtiyacınız var . Aksi takdirde, çocuk unsurları bunu etkileyecek
Aşağıdakiler, tuval öğesiyle fare konum ilişkisini hesaplar:
var example = document.getElementById('example');
example.onmousemove = function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
}
Bu örnekte, öğeye this
atıfta bulunur ve olaydır.example
e
onmousemove
var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
this
için e.currentTarget
size etkinlik dinleyici ekledi elemana konumunu alacak.
Saf javascript'te, referans eleman mutlak konumlandırma ile olabilen diğerlerinin içine yerleştirildiğinde göreceli koordinatlar döndüren bir cevap yoktur. İşte bu senaryoya bir çözüm:
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,
};
}
html
öğe ofset dikkate alır sanmıyorum
while(reference !== undefined)
ile while(reference)
. En azından Chrome'da, offsetParent olmakla kalmaz undefined
, aynı zamanda null
. Sadece doğru olup olmadığını kontrol etmek reference
, hem undefined
ve hem de ile çalışmasını sağlayacaktır null
.
offsetParent
Başka durumlarda çok yararlı olduğu ortaya çıkan bir mülk olduğunu bana bildirerek, yapabilseydim başka bir +1 verirdim !
scrollLeft
ve scrollTop
telafi etmeniz gerekiyor .
Bu sorunun zorluğuna ilişkin iyi bir yazıyı burada bulabilirsiniz: http://www.quirksmode.org/js/events_properties.html#position
Burada açıklanan tekniği kullanarak farelerin konumunu belgedeki bulabilirsiniz. Sonra sadece size arayarak bulabilirsiniz elemanının sınırlayıcı kutunun içinde olup olmadığını kontrol edin element.getBoundingClientRect()
: Aşağıdaki özelliklere sahip bir nesne döndürür { bottom, height, left, right, top, width }
. Oradan bile elemanınızın içinde olup olmadığını anlamak önemsizdir.
Tüm bu çözümleri denedim ve özel kurulum nedeniyle bir matris dönüştürülmüş konteyner (panzoom kütüphanesi) hiçbiri işe yaramadı. Bu, yakınlaştırılmış ve yatay kaydırılmış olsa bile doğru değeri döndürür:
mouseevent(e) {
const x = e.offsetX,
y = e.offsetY
}
Ama sadece yolda alt öğe yoksa. Bu, CSS kullanılarak etkinliğe 'görünmez' hale getirilerek atlatılabilir:
.child {
pointer-events: none;
}
Bu soru geldi, ama benim durum için çalışmasını sağlamak için (() benim durumumda tuval olmadığı DOM-elemana DragOver kullanarak), ben sadece kullanmak zorunda olduğunu tespit offsetX
ve offsetY
dragover-fare olayı .
onDragOver(event){
var x = event.offsetX;
var y = event.offsetY;
}
Mark van Wyk'un cevabı beni doğru yöne götürdüğü için + 1'ledi, ama benim için tam olarak çözmedi. Hala başka bir elementin içindeki elementlerdeki resim üzerinde bir ofset vardı.
Aşağıdaki benim için çözdü:
x = e.pageX - this.offsetLeft - $(elem).offset().left;
y = e.pageY - this.offsetTop - $(elem).offset().top;
Başka bir deyişle - ben sadece iç içe tüm unsurların ofset istif
Yukarıdaki cevapların hiçbiri tatmin edici IMO değildir, bu yüzden kullanıyorum:
// 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);
}
Sayfanın geçerli Y kaydırma konumunu bilmeniz gerekirse:
var yscroll = window.pageYOffset
|| (document.documentElement && document.documentElement.scrollTop)
|| document.body.scrollTop; // scroll Y position in page
Mobil cihazlar ve / veya dokunmatik ekranlı dizüstü bilgisayarlar / monitörler için normal web siteleri veya PWA'lar (Aşamalı Web Uygulamaları) geliştirenler için, fare olaylarına alışık olabileceğiniz ve bazen acı verici Touch deneyiminde yeni olabileceğiniz için buraya geldiniz olaylar ... yay!
Sadece 3 kural vardır:
mousemove
Veya sırasında mümkün olduğunca az yapıntouchmove
olaylar.mousedown
Veya sırasında mümkün olduğunca çok şey yapıntouchstart
olaylar.Söylemeye gerek yok, touch
olaylar olaylarla daha karmaşıktır, çünkü birden fazla olabilir ve fare olaylarından daha esnek (karmaşık )dır. Burada sadece tek bir dokunuşu ele alacağım. Evet, tembelim, ama en yaygın dokunuş türü, bu yüzden orada.
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.
Vue.js kullanmayı tercih ediyor musunuz? Yaparım! Ardından HTML'niz şöyle görünür:
<div @mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@touchstart.stop.prevent="handleTouchStart"
@touchmove.stop.prevent="handleTouchMove"
@touchend.stop.prevent="handleTouchEnd">
tarafından alabilirsiniz
var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
var xCoor = e.clientX;
var yCoor = e.clientY;
}
Alındığı Bu eğitimde üst yorumun sayesinde yapılan düzeltmelerle:
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 )
};
}
Bir tuval üzerinde aşağıdaki gibi kullanın:
var canvas = document.getElementById( 'myCanvas' );
canvas.addEventListener( 'mousemove', function( evt ) {
var mousePos = getMousePos( canvas, evt );
} );
Biraz geç kaldığımı anlıyorum, ancak bu PURE javascript ile çalışıyor ve öğe görünüm penceresinden daha büyükse ve kullanıcı kaydırdıysa, öğenin içindeki işaretçinin koordinatlarını bile veriyor.
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 ;
}
Nasıl çalışır.
İlk yaptığımız şey HTML öğesinin (içerik alanı) geçerli görünüm penceresine göre konumunu almaktır. Sayfada kaydırma çubukları varsa ve kaydırılırsa, tarafından döndürülen sayıgetBoundingClientRect().left
html etiketi için negatif olur. Daha sonra bu sayıyı, öğe ile içerik alanının solu arasındaki mesafeyi hesaplamak için kullanırız. İleelement_offset_x = element.getBoundingClientRect().left......;
Elemanın içerik alanından uzaklığını bilmek. event.clientX
bize işaretçinin görünümden uzaklığını verir. Görünüm penceresinin ve içerik alanının iki farklı varlık olduğunu anlamak önemlidir, sayfa kaydırıldığında görünüm alanı hareket edebilir. Bu nedenle, sayfa kaydırılsa bile clientX AYNI numarayı döndürür.
Bunu telafi etmek için işaretçinin x konumunu (görünüm penceresine göre), görünüm penceresinin x konumuna (içerik alanına göre) eklememiz gerekir. Görünüm penceresinin X konumu şununla bulunur: window.pageXOffset.
@ Spider'ın çözümüne dayanarak, benim JQuery olmayan sürümüm şudur:
// 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;
}
Bu hem kaydırma hem de yakınlaştırma ile çalışır (bu durumda bazen yüzer döndürür).
Bir tuval içindeki fare koordinatları event.offsetX ve event.offsetY sayesinde elde edilebilir. Demek istediğimi kanıtlamak için küçük bir pasaj:
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>
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
Salt HTMLElement.offsetLeft
okunur özelliği, geçerli öğenin sol üst köşesinin,HTMLElement.offsetParent
düğüm .
Blok düzeyi elemanlar için offsetTop
, offsetLeft
, offsetWidth
ve offsetHeight
bir elemanın nisbetle sınır kutusunun tarif offsetParent
.
Bununla birlikte, (örneğin, içi seviyesi elemanları için span
bir satır bir sonraki kaydırmak, olabilir) offsetTop
ve offsetLeft
(kullanımı ilk sınır kutusunun konumlarını tanımlayan Element.getClientRects()
genişliği ve yüksekliği elde etmek için), süre offsetWidth
ve offsetHeight
sınırlayıcı sınır kutusunun boyutları tarif ( Element.getBoundingClientRect()
konumunu almak için kullanın ). Bu nedenle sol üst, genişlik ve yüksekliğe sahip bir kutu offsetLeft
, offsetTop
, offsetWidth
ve offsetHeight
sarılı metin ile bir zaman dilimi için bir sınırlama kutusu olmayacaktır.
HTMLElement.offsetTop
Salt HTMLElement.offsetTop
okunur özelliği, geçerli öğenin offsetParent
düğümün tepesine göre uzaklığını döndürür .
MouseEvent.pageX
Salt pageX
okunur özelliği, tüm belgeye göre olayın pikselleri olarak X (yatay) koordinatını döndürür. Bu özellik, sayfanın yatay kaydırılmasını dikkate alır.
MouseEvent.pageY
MouseEvent.pageY
okunur özelliği, tüm belgeye göre olayın piksel cinsinden Y (dikey) koordinatını döndürür. Bu özellik, sayfanın dikey kaydırılmasını dikkate alır.
Daha fazla açıklama için lütfen Mozilla Geliştirici Ağı'na bakın:
https://developer.mozilla.org/tr-TR/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
page
ve offset
bana çok yardımcı olacaktır. Bu isteği düşündüğünüz için teşekkür ederiz!
Çok basit olduğunu düşündüğüm başka bir çözüm uyguladım, bu yüzden sizinle paylaşacağımı düşündüm.
Benim için sorun, sürüklenen div'ın fare imleci için 0,0'a atlamasıydı . Bu yüzden div yeni konumunu ayarlamak için div fareler konumunu yakalamak gerekiyordu.
PageX ve PageY divlerini okudum ve buna göre üst ve solu ayarladım ve sonra imleci div'da ilk konumda tutmak için koordinatları ayarlamak için değerleri almak için bir onDragStart dinleyicisi kullanıyorum ve e.nativeEvent'i saklıyorum .layerX ve e.nativeEvent.layerY sadece ilk tetikleyicide size sürüklenebilir div içindeki farelerin konumunu verir.
Örnek 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,
});
}
Umarım bu yaşadığım aynı problemleri yaşayan birine yardımcı olur :)
Sayfanızın yapısını bilmelisiniz, çünkü eğer tuvaliniz bir div'ın çocuğu ise, bu da başka bir div'ın çocuğuysa ... hikaye daha karmaşık hale gelir. İşte div s 2 seviyeleri içinde bir tuval için benim kod:
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);
});
Orijinal cevap bir iframe koymak söyledi. Daha iyi çözüm, dolgu 0px olarak ayarlanmış bir tuval üzerinde offsetX ve offsetY olaylarını kullanmaktır.
<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>
Sen kullanabilirsiniz getBoudingClientRect()
ait relative
ebeveyn.
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)
})