Tarayıcı penceresine göre JavaScript gibi img
ve div
JavaScript gibi HTML öğelerinin X ve Y konumlarını nasıl alacağımı bilmek istiyorum .
Tarayıcı penceresine göre JavaScript gibi img
ve div
JavaScript gibi HTML öğelerinin X ve Y konumlarını nasıl alacağımı bilmek istiyorum .
Yanıtlar:
Doğru yaklaşım aşağıdakileri kullanmaktır element.getBoundingClientRect()
:
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
Internet Explorer bunu umursadığınız ve sonunda CSSOM Görünümlerinde standartlaştırıldığı sürece destekledi . Diğer tüm tarayıcılar bunu uzun zaman önce kabul ettiler .
Bazı tarayıcılar da yükseklik ve genişlik özelliklerini döndürür, ancak bu standart değildir. Daha eski tarayıcı uyumluluğu konusunda endişeleriniz varsa, optimize edilmiş bir düşürme uygulaması için bu yanıtın düzeltmelerini kontrol edin.
Tarafından döndürülen değerler element.getBoundingClientRect()
görünüm penceresine göredir. Başka bir öğeye göre buna ihtiyacınız varsa, bir dikdörtgeni diğerinden çıkarın:
var bodyRect = document.body.getBoundingClientRect(),
elemRect = element.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
alert('Element is ' + offset + ' vertical pixels from <body>');
<body>
.
element.getBoundingClientRect().top
position: fixed
odaklanmış bir giriş öğesi içeriyorsa ve sanal klavye kaydırılmışsa iOS'ta bir öğenin (iPhone 8) doğru üst ofseti döndürmez . Örneğin, pencerenin üst kısmındaki gerçek ofset 200 piksel ise, bunu 420 piksel olarak bildirir, burada 220 piksel sanal klavyenin yüksekliği olur. Elemanları ayarlar position: absolute
ve sabitlenmiş konumla aynı konuma yerleştirirseniz, doğru 200 pikseli alırsınız. Buna bir çözüm bilmiyorum.
Kütüphaneler, bir eleman için doğru ofsetleri elde etmek için bazı uzunluklara giderler.
İşte denediğim her koşulda işi yapan basit bir işlev.
function getOffset( el ) {
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
var x = getOffset( document.getElementById('yourElId') ).left;
Bu benim için çalıştı (en çok oy verilen cevaptan değiştirildi):
function getOffset(el) {
const rect = el.getBoundingClientRect();
return {
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};
}
Bunu kullanarak arayabiliriz
getOffset(element).left
veya
getOffset(element).top
div
css kullanılarak ortalanmış eleman yerleştirildiğinde benim için çalışıyor top:50%, left:50%; transform:translate(-50%, -50%);
... mükemmel. @ScottBiggs sorusu katılıyorum. Mantık, basitliği aramaktır.
rect
kullanarak var
, let
ya da const
. Aksi takdirde, olarak tanımlanır window.rect
.
left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)
bir elementin orta pozisyonunu döndürür
Eğer sadece javascript olmasını istiyorsan , burada bazıları şunlardır biri gömlekleri kullanarakgetBoundingClientRect()
window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y
window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X
İlk satır offsetTop
belgeye göre Y diyecektir. İkinci satır offsetLeft
X'e göre belgeye göre dönecektir .
getBoundingClientRect()
, pencerenin görünümüne göre öğenin konumunu döndüren bir javascript işlevidir.
Çoğu tarayıcıdaki HTML öğelerinde şunlar bulunur: -
offsetLeft
offsetTop
Bunlar, öğenin yerleşime sahip en yakın üst öğeye göre konumunu belirtir. Bu üst öğeye genellikle offsetParent özelliğinde erişilebilir.
IE ve FF3
clientLeft
clientTop
Bu özellikler daha az yaygındır, üst öğe istemci alanı ile bir öğe konumu belirtirler (dolgulu alan istemci alanının bir parçasıdır ancak kenarlık ve kenar boşluğu değildir).
Sayfa - en azından herhangi bir "DIV" içeriyorsa, meouw tarafından verilen işlev "Y" değerini geçerli sayfa sınırlarının ötesine atar. Tam konumu bulmak için, hem offsetParent'leri hem de parentNode'ları ele almanız gerekir.
Aşağıda verilen kodu deneyin (FF2 için kontrol edilir):
var getAbsPosition = function(el){
var el2 = el;
var curtop = 0;
var curleft = 0;
if (document.getElementById || document.all) {
do {
curleft += el.offsetLeft-el.scrollLeft;
curtop += el.offsetTop-el.scrollTop;
el = el.offsetParent;
el2 = el2.parentNode;
while (el2 != el) {
curleft -= el2.scrollLeft;
curtop -= el2.scrollTop;
el2 = el2.parentNode;
}
} while (el.offsetParent);
} else if (document.layers) {
curtop += el.y;
curleft += el.x;
}
return [curtop, curleft];
};
Element.prototype
Herhangi bir öğenin üstünü / solunu almak için iki özellik ekleyebilirsiniz .
Object.defineProperty( Element.prototype, 'documentOffsetTop', {
get: function () {
return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
}
} );
Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
get: function () {
return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
}
} );
Buna şöyle denir:
var x = document.getElementById( 'myDiv' ).documentOffsetLeft;
Sonuçları jQuery's offset().top
ile karşılaştıran bir demo .left
: http://jsfiddle.net/ThinkingStiff/3G7EZ/
Element.prototype
genellikle kötü bir fikir olarak kabul edilir . Kodun korunması gerçekten zor. Ayrıca, bu kod kaydırmayı hesaba katmaz.
Sayfaya göre konumu etkin bir şekilde ve özyinelemeli bir işlev kullanmadan almak için: (IE'yi de içerir)
var element = document.getElementById('elementId'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?
document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
Buna benzer bir şeye, öğenin kimliğini ileterek sola veya üste dönecek, bunları da birleştirebiliriz:
1) sola bul
function findLeft(element) {
var rec = document.getElementById(element).getBoundingClientRect();
return rec.left + window.scrollX;
} //call it like findLeft('#header');
2) üst bulmak
function findTop(element) {
var rec = document.getElementById(element).getBoundingClientRect();
return rec.top + window.scrollY;
} //call it like findTop('#header');
veya 3) sola ve üste birlikte bul
function findTopLeft(element) {
var rec = document.getElementById(element).getBoundingClientRect();
return {top: rec.top + window.scrollY, left: rec.left + window.scrollX};
} //call it like findTopLeft('#header');
Tarayıcıdan bağımsız bir şekilde bu tür bilgileri (ve çok daha fazlasını!) Döndüren işlevlere sahip bir JavaScript çerçevesi kullanarak daha iyi hizmet verebilirsiniz. Burda biraz var:
Bu çerçevelerle, şöyle bir şey yapabilirsiniz:
$('id-of-img').top
görüntünün y-piksel koordinatını elde etmek için.
jQuery .offset () , ilk öğenin geçerli koordinatlarını alır veya her öğenin koordinatlarını, belgeye göre eşleşen öğeler kümesinde ayarlar.
@Meouw'un cevabını aldım, sınıra izin veren clientLeft'e ekledim ve üç sürüm oluşturdum:
getAbsoluteOffsetFromBody - @ meouw'lara benzer şekilde, bu belgenin gövdesine veya html öğesine göre mutlak konumu alır (tuhaflık moduna bağlı olarak)
getAbsoluteOffsetFromGivenElement - verilen öğeye (relativeEl) göre mutlak konumu döndürür. Verilen öğenin el öğesini içermesi gerektiğini, aksi takdirde getAbsoluteOffsetFromBody ile aynı şekilde davranacağını unutmayın. Başka bir (bilinen) öğede (isteğe bağlı olarak düğüm ağacının üstündeki birkaç düğüm) bulunan iki öğeniz varsa ve bunları aynı konuma getirmek istiyorsanız bu yararlıdır.
getAbsoluteOffsetFromRelative - position: relative ile ilk üst öğeye göre mutlak konumu döndürür. Bu, aynı nedenle getAbsoluteOffsetFromGivenElement öğesine benzer, ancak yalnızca ilk eşleşen öğeye kadar gider.
getAbsoluteOffsetFromBody = function( el )
{ // finds the offset of el from the body or html element
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{ // finds the offset of el from relativeEl
var _x = 0;
var _y = 0;
while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
getAbsoluteOffsetFromRelative = function( el )
{ // finds the offset of el from the first parent with position: relative
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
if (el != null)
{
if (getComputedStyle !== 'undefined')
valString = getComputedStyle(el, null).getPropertyValue('position');
else
valString = el.currentStyle['position'];
if (valString === "relative")
el = null;
}
}
return { top: _y, left: _x };
}
Özellikle kaydırma ile ilgili hala sorun yaşıyorsanız, http://www.greywyvern.com/?post=331 - getStyle'de tarayıcıların davrandığını varsayarak en az bir şüpheli kod parçasını fark etmeyi deneyebilirsiniz. , ama geri kalanını hiç test etmedim.
jQuery kullanıyorsanız, dimension eklentisi mükemmeldir ve tam olarak ne istediğinizi belirtmenize izin verir.
Örneğin
Bağıl pozisyon, mutlak pozisyon, dolgu olmadan mutlak pozisyon, dolgu ile ...
Devam ediyor, diyelim ki yapabileceğiniz çok şey var.
Ayrıca jQuery kullanmanın avantajı, hafif dosya boyutu ve kolay kullanımıdır, daha sonra JavaScript olmadan geri dönmeyeceksiniz.
Bu oluşturmayı başardığım en iyi kod (jQuery'nin ofsetinden () farklı olarak iframe'lerde de çalışır). Webkit biraz farklı bir davranış var gibi görünüyor.
Meouw'un yorumuna dayanarak:
function getOffset( el ) {
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;
// chrome/safari
if ($.browser.webkit) {
el = el.parentNode;
} else {
// firefox/IE
el = el.offsetParent;
}
}
return { top: _y, left: _x };
}
JQuery kullanıyorsanız, bu basit bir çözüm olabilir:
<script>
var el = $("#element");
var position = el.position();
console.log( "left: " + position.left + ", top: " + position.top );
</script>
Küçük ve küçük arasındaki fark
function getPosition( el ) {
var x = 0;
var y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
x += el.offsetLeft - el.scrollLeft;
y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: y, left: x };
}
Örnek bir koordinatlara bakın: http://javascript.info/tutorial/coordinates
<svg>
elemanlar, örneğin, yok offsetLeft
, offsetTop
ve offsetParent
özellikleri.
DIV
ya da IMG
değil SVG
. "Bir örnek koordinatlara bakın" görünümü? nesne svg konum çağrı getOffsetRect , bulabilirsiniz deneyin nesne çalışma bağlıdır.
Bulduğum en temiz yaklaşım, jQuery's tarafından kullanılan tekniğin basitleştirilmiş bir versiyonudur offset
. Başladığı diğer cevaplara benzer şekilde getBoundingClientRect
; o zaman kullandığı window
ve documentElement
üzerinde marjı gibi kaydırma konumuna yanı sıra şeyleri ayarlamak için body
(genellikle varsayılan).
var rect = el.getBoundingClientRect();
var docEl = document.documentElement;
var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;
Bu, birçok cevabın altında kaybolması muhtemel olsa da, buradaki en iyi çözümler benim için işe yaramıyordu.
Anlayabildiğim kadarıyla diğer cevapların hiçbiri yardımcı olmazdı.
Durum :
HTML5 sayfasında bir üstbilginin içinde bir gezinme öğesi olan bir menü vardı (üstbilgi değil, başka bir öğedeki üstbilgi).
Kullanıcı bir kez kaydırdığında navigasyonun üstüne yapışmasını istedim, ancak bundan önce başlık mutlak konumlandırıldı (bu yüzden biraz başka bir şey kaplayabilirim).
Yukarıdaki çözümler hiçbir zaman bir değişikliği tetiklemedi, çünkü .offsetTop değişmeyecek çünkü bu mutlak konumlandırılmış bir elemandı. Ayrıca .scrollTop özelliği en üstteki öğenin en tepesindeydi ... yani 0'dır ve her zaman 0 olur.
Bu ikisini kullanarak yaptığım herhangi bir test (ve getBoundingClientRect sonuçlarıyla aynı), gezinme çubuğunun üst kısmının görüntülenebilir sayfanın üstüne kaydırılıp kaydırılmadığını (yine, konsolda bildirildiği gibi, aynı sayıları kaydırırken aynı kaldıklarını) söylemez ) oluştu.
Çözüm
Benim için çözüm
window.visualViewport.pageTop
PageTop özelliğinin değeri, ekranın görüntülenebilir bölümünü yansıtır, böylece bir öğenin görüntülenebilir alanın sınırlarına referansta bulunduğunu izlememe izin verir.
Muhtemelen kaydırma ile uğraştığım zaman gereksizdir, kaydırılan öğelerin hareketine programlı olarak yanıt vermek için bu çözümü kullanmayı umuyorum.
Umarım başka birine yardımcı olur.
ÖNEMLİ NOT: Bu şu anda Chrome ve Opera'da çalışıyor ve Firefox'ta (6-2018) çalışmıyor ... Firefox visualViewport'u destekleyene kadar Bu yöntemi kullanmamanızı öneririm (ve umarım yakında yaparlar ... çok şey yapar diğerlerinden daha mantıklı).
GÜNCELLEME:
Bu çözümle ilgili sadece bir not.
Hâlâ keşfettiğim şeyi, "... kaydırılan öğelerin hareketine programlı olarak yanıt verdiği" durumlar için çok değerli buluyorum. uygulanabilir. Sahip olduğum problem için daha iyi çözüm, pozisyonu ayarlamak için CSS kullanmaktı : yapışkaneleman üzerinde. Yapışkan kullanarak javascript kullanmadan üst kısmında bir eleman kalmasını sağlayabilirsiniz (NOT: Bu çalışma, sabit ama çoğu kullanımlar için yapışkan yaklaşım olasılıkla daha üstün olacak kadar eleman değişen etkili bir alışkanlık olduğu kadar zamanlar vardır)
: UPDATE01
Ben fark farklı bir sayfa için, hafif karmaşık bir kaydırma kurulumunda (paralaks artı mesajın bir parçası olarak geçmiş kaydırma öğeleri) bir öğenin konumunu tespit etmek için gerekli bir gereksinimim vardı. Bu senaryoda, aşağıdakilerin bir şeyi ne zaman yapacağımı belirlemek için kullandığım değeri sağladığını fark ettim:
let bodyElement = document.getElementsByTagName('body')[0];
let elementToTrack = bodyElement.querySelector('.trackme');
trackedObjPos = elementToTrack.getBoundingClientRect().top;
if(trackedObjPos > 264)
{
bodyElement.style.cssText = '';
}
Umarım bu cevap şimdi daha yaygındır.
Bunu böyle yaptım, bu yüzden eski tarayıcılarla çapraz uyumluydu.
// For really old browser's or incompatible ones
function getOffsetSum(elem) {
var top = 0,
left = 0,
bottom = 0,
right = 0
var width = elem.offsetWidth;
var height = elem.offsetHeight;
while (elem) {
top += elem.offsetTop;
left += elem.offsetLeft;
elem = elem.offsetParent;
}
right = left + width;
bottom = top + height;
return {
top: top,
left: left,
bottom: bottom,
right: right,
}
}
function getOffsetRect(elem) {
var box = elem.getBoundingClientRect();
var body = document.body;
var docElem = document.documentElement;
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop;
var clientLeft = docElem.clientLeft;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
var bottom = top + (box.bottom - box.top);
var right = left + (box.right - box.left);
return {
top: Math.round(top),
left: Math.round(left),
bottom: Math.round(bottom),
right: Math.round(right),
}
}
function getOffset(elem) {
if (elem) {
if (elem.getBoundingClientRect) {
return getOffsetRect(elem);
} else { // old browser
return getOffsetSum(elem);
}
} else
return null;
}
JavaScript'teki koordinatlar hakkında daha fazla bilgiyi burada bulabilirsiniz: http://javascript.info/tutorial/coordinates
Bir öğenin toplam ofsetini elde etmek için, tüm üst ofsetleri özyinelemeli olarak özetleyebilirsiniz:
function getParentOffsets(el): number {
if (el.offsetParent) {
return el.offsetParent.offsetTop + getParentOffset(el.offsetParent);
} else {
return 0;
}
}
bu yardımcı program fonksiyonu ile bir dom öğesinin toplam üst ofseti:
el.offsetTop + getParentOffsets(el);
/**
*
* @param {HTMLElement} el
* @return {{top: number, left: number}}
*/
function getDocumentOffsetPosition(el) {
var position = {
top: el.offsetTop,
left: el.offsetLeft
};
if (el.offsetParent) {
var parentPosition = getDocumentOffsetPosition(el.offsetParent);
position.top += parentPosition.top;
position.left += parentPosition.left;
}
return position;
}
Cevabınız için ThinkingStiff'e teşekkür ederiz , bu sadece başka bir versiyonudur.
Kullanıcının bir tablo satırında hangi bağlantıyı tıkladığına bağlı olarak bir bootstrap 2 modunu konumlandırmak için Andy E'nin çözümünü başarıyla kullandım. Sayfa bir Goblen 5 sayfasıdır ve aşağıdaki javascript java sayfa sınıfına aktarılmıştır.
javascript:
function setLinkPosition(clientId){
var bodyRect = document.body.getBoundingClientRect(),
elemRect = clientId.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
offset = offset + 20;
$('#serviceLineModal').css("top", offset);
}
Modsal kodum:
<div id="serviceLineModal" class="modal hide fade add-absolute-position" data-backdrop="static"
tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="top:50%;">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h3 id="myModalLabel">Modal header</h3>
</div>
<div class="modal-body">
<t:zone t:id="modalZone" id="modalZone">
<p>You selected service line number: ${serviceLineNumberSelected}</p>
</t:zone>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<!-- <button class="btn btn-primary">Save changes</button> -->
</div>
Döngüdeki bağlantı:
<t:loop source="servicesToDisplay" value="service" encoder="encoder">
<tr style="border-right: 1px solid black;">
<td style="white-space:nowrap;" class="add-padding-left-and-right no-border">
<a t:type="eventLink" t:event="serviceLineNumberSelected" t:context="service.serviceLineNumber"
t:zone="pageZone" t:clientId="modalLink${service.serviceLineNumber}"
onmouseover="setLinkPosition(this);">
<i class="icon-chevron-down"></i> <!-- ${service.serviceLineNumber} -->
</a>
</td>
Ve sayfa sınıfındaki java kodu:
void onServiceLineNumberSelected(String number){
checkForNullSession();
serviceLineNumberSelected = number;
addOpenServiceLineDialogCommand();
ajaxResponseRenderer.addRender(modalZone);
}
protected void addOpenServiceLineDialogCommand() {
ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
@Override
public void run(JavaScriptSupport javascriptSupport) {
javascriptSupport.addScript("$('#serviceLineModal').modal('show');");
}
});
}
Umarım bu birine yardımcı olur, bu yazı yardımcı oldu.
Çok araştırma ve testten sonra bu işe yarıyor gibi görünüyor
function getPosition(e) {
var isNotFirefox = (navigator.userAgent.toLowerCase().indexOf('firefox') == -1);
var x = 0, y = 0;
while (e) {
x += e.offsetLeft - e.scrollLeft + (isNotFirefox ? e.clientLeft : 0);
y += e.offsetTop - e.scrollTop + (isNotFirefox ? e.clientTop : 0);
e = e.offsetParent;
}
return { x: x + window.scrollX, y: y + window.scrollY };
}
Sadece bunu orada da atacağımı düşündüm.
Eski tarayıcılarda test edemedim, ancak en son 3'te çalışıyor. :)
Element.prototype.getOffsetTop = function() {
return ( this.parentElement )? this.offsetTop + this.parentElement.getOffsetTop(): this.offsetTop;
};
Element.prototype.getOffsetLeft = function() {
return ( this.parentElement )? this.offsetLeft + this.parentElement.getOffsetLeft(): this.offsetLeft;
};
Element.prototype.getOffset = function() {
return {'left':this.getOffsetLeft(),'top':this.getOffsetTop()};
};
Farklı tarayıcılar kenarlık, dolgu, kenar boşluğu vb. Kesin boyutta istediğiniz her kök öğede belirli bir öğenin üst ve sol konumlarını almak için küçük bir işlev yazdım:
function getTop(root, offset) {
var rootRect = root.getBoundingClientRect();
var offsetRect = offset.getBoundingClientRect();
return offsetRect.top - rootRect.top;
}
Sol pozisyonu geri almak için:
return offsetRect.left - rootRect.left;
Sola ve Yukarıya göre div pozisyonunu al
var elm = $('#div_id'); //get the div
var posY_top = elm.offset().top; //get the position from top
var posX_left = elm.offset().left; //get the position from left
el.offsetTop
ve el.offsetLeft
(OP jQuery hakkında bir şey söylemiyor ... Cevabınızın neden jQuery kullandığından emin değilim ...)