JQuery ile bir div'in görünür yüksekliğini alın


87

Kaydırılabilir bir alan içindeki bir div'in görünür yüksekliğini almam gerekiyor. JQuery konusunda kendimi oldukça iyi görüyorum, ancak bu beni tamamen atıyor.

Diyelim ki siyah bir sarmalayıcı içinde kırmızı bir div var:

Yukarıdaki grafikte jQuery işlevi, div'in görünür kısmı olan 248'i döndürecektir.

Yukarıdaki grafikte olduğu gibi, kullanıcı div'in üst kısmını kaydırdığında 296'yı bildirir.

Şimdi, kullanıcı div'i geçtikten sonra tekrar 248'i rapor edecektir.

Açıkçası, rakamlarım bu demodaki kadar tutarlı ve net olmayacak, yoksa bu numaralar için kodlama yapardım.

Biraz teorim var:

  • Pencerenin yüksekliğini alın
  • Div yüksekliğini alın
  • Pencerenin üstünden div'in ilk ofsetini alın
  • Kullanıcı kaydırdıkça ofseti alın.
    • Göreli konum pozitifse, div'in tepesinin hala görünür olduğu anlamına gelir.
    • negatifse, div'in üst kısmı pencere tarafından gölgelenmiştir. Bu noktada, div pencerenin tüm yüksekliğini kaplıyor olabilir veya div'in alt kısmı gösteriliyor olabilir
    • Div'in altı gösteriliyorsa, bununla pencerenin altı arasındaki boşluğu bulun.

Oldukça basit görünüyor, ama kafamı dolanamıyorum. Yarın sabah başka bir çatlak alacağım; Bazı dahilerin yardımcı olabileceğini düşündüm.

Teşekkürler!

GÜNCELLEME: Bunu kendi başıma çözdüm, ancak aşağıdaki cevaplardan biri daha zarif görünüyor, bu yüzden onun yerine onu kullanacağım. Merak edenler için, işte bulduğum şey:

$(document).ready(function() {
    var windowHeight = $(window).height();
    var overviewHeight = $("#overview").height();
    var overviewStaticTop = $("#overview").offset().top;
    var overviewScrollTop = overviewStaticTop - $(window).scrollTop();
    var overviewStaticBottom = overviewStaticTop + $("#overview").height();
    var overviewScrollBottom = windowHeight - (overviewStaticBottom - $(window).scrollTop());
    var visibleArea;
    if ((overviewHeight + overviewScrollTop) < windowHeight) {
        // alert("bottom is showing!");
        visibleArea = windowHeight - overviewScrollBottom;
        // alert(visibleArea);
    } else {
        if (overviewScrollTop < 0) {
            // alert("is full height");
            visibleArea = windowHeight;
            // alert(visibleArea);
        } else {
            // alert("top is showing");
            visibleArea = windowHeight - overviewScrollTop;
            // alert(visibleArea);
        }
    }
});

Vh birimlerine bakardım. 1vh = Görüntü alanı yüksekliğinin 1 / 100'ü. Muhtemelen bununla bir çözüm bulacaksınız. Görüntü alanının yüksekliğini, öğenin yüksekliğini, öğelerin konumunu ve kaydırma konumunu bulun ve buna göre hesaplayın.
davidcondrey

İç DIV'de bir marj olduğunu varsayarak, her yerde "10px" deyin. "10" u geçip geçmediğini görmek için kaydırma yüksekliğini tespit ederdim, sonra sadece ana öğenin yüksekliğini alırdım, kaydırma yüksekliğine göre onu çıkarırdım.

: Bütün bunlardan başarısız olursa, ben sadece böyle görünüyor sen gerekmez amaca hizmet edebilir, bu komut dosyası rastladım larsjung.de/fracs
davidcondrey

Yanıtlar:


58

İşte hızlı ve kirli bir konsept. Temel offset().topolarak, öğenin penceresinin üst kısmıyla ve pencerenin offset().top + height()alt kısmıyla karşılaştırır:

function getVisible() {    
    var $el = $('#foo'),
        scrollTop = $(this).scrollTop(),
        scrollBot = scrollTop + $(this).height(),
        elTop = $el.offset().top,
        elBottom = elTop + $el.outerHeight(),
        visibleTop = elTop < scrollTop ? scrollTop : elTop,
        visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
    $('#notification').text(visibleBottom - visibleTop);
}

$(window).on('scroll resize', getVisible);

Örnek keman

düzenle - pencere yeniden boyutlandırılırken mantığı da gerçekleştirmek için küçük güncelleme.


divKodu tekrarlamadan bunu birden çok s için ayarlamada sorun yaşıyorum . Bunu yapmanın bir yolu var mı?
JacobTheDev

2
@Rev buraya gidin: jsfiddle.net/b5DGj/1 . Her öğeyi kendi işlev çağrısına ayırdım. Hatta daha ileri gidebilir ve bunu sizin için yapacak bir eklenti tanımlayabilirsiniz.
Rory McCrossan

@ RoryMcCrossan'ın jQuery eklentisi olarak işlev görme yaklaşımını biraz yeniden yazdım ve aşağıda bir cevap olarak gönderdim - bu formatta daha genel uygulanabilirliğe sahip olabilir.
Michael.Lumley

Bazen bir öğe, taşma veya ana öğeler nedeniyle, "pencere" ne olursa olsun kısmen gizlenebilir
Nadav B

56

Bir öğenin (yükseklik) görüntü alanında olduğu piksel miktarını hesaplayın

Fiddle demosu

Bu küçük işlev , pxbir öğenin (dikey) Görünüm Penceresinde görünen miktarını döndürür :

function inViewport($el) {
    var elH = $el.outerHeight(),
        H   = $(window).height(),
        r   = $el[0].getBoundingClientRect(), t=r.top, b=r.bottom;
    return Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H));
}

Gibi kullanın:

$(window).on("scroll resize", function(){
  console.log( inViewport($('#elementID')) ); // n px in viewport
});

bu kadar.


jQuery .inViewport()Eklentisi

jsFiddle demosu

yukarıdan mantığı çıkarabilir ve bunun gibi bir eklenti oluşturabilirsiniz:

/**
 * inViewport jQuery plugin by Roko C.B.
 * http://stackoverflow.com/a/26831113/383904
 * Returns a callback function with an argument holding
 * the current amount of px an element is visible in viewport
 * (The min returned value is 0 (element outside of viewport)
 */
;(function($, win) {
  $.fn.inViewport = function(cb) {
     return this.each(function(i,el) {
       function visPx(){
         var elH = $(el).outerHeight(),
             H = $(win).height(),
             r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
         return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H)));  
       }
       visPx();
       $(win).on("resize scroll", visPx);
     });
  };
}(jQuery, window));

Gibi kullanın:

$("selector").inViewport(function(px) {
  console.log( px ); // `px` represents the amount of visible height
  if(px > 0) {
    // do this if element enters the viewport // px > 0
  }else{
    // do that if element exits  the viewport // px = 0
  }
}); // Here you can chain other jQuery methods to your selector

seçicileriniz dinamik olarak pencereyi dinleyecek scrollve resizeaynı zamanda ilk geri arama işlevi bağımsız değişkeni aracılığıyla DOM hazırda başlangıç ​​değerini döndürecektir px.


Android Chrome'da çalışmak için <meta name="viewport" content="width=your_size">head html bölümüne eklemeniz gerekebilir .
userlond

@userlond katkınız için teşekkürler, ancak content="width=1259"çoğunluk için uygun olduğundan emin değilim . Onun content="width=device-width, initial-scale=1"yerine denedin mi?
Roko C. Buljan

Sitenin sabit genişlikte eski bir şablonu var ve yanıt vermiyor ... Önerinizin çoğunluk için uygun olacağını düşünüyorum. Yani netleştirmek için: Roko C. Buljan çözümü değil işi yaparsa eklemeyi deneyin <meta name="viewport" content="your_content">beyanı :)
userlond

Bu çok harika ve aradığıma çok yakın. Öğelerin altından pencerenin altına kadar olan mesafeyi nasıl hesaplayabilirim? Böylece siz içeriğin sonunu görmeden daha fazla içerik yükleyebilirim. Örneğin, windowBot'tan elBottom <200 ise AJAX'ı ateşleyin.
Thom

1
@Thom, yukarıdaki yöntem başka herhangi bir belirli değer döndürmez ( visible height pxbir nesne gibi yalnızca daha fazlasını döndürmek için genişletilebilir . Böyle bir fikir için bu kemana bakın: jsfiddle.net/RokoCB/6xjq5gyy (geliştirici konsolunu aç günlükleri görmek için)
Roko C. Buljan

11

JQuery eklentisi olarak işlev görecek şekilde yazılması dışında, yukarıdaki Rory yaklaşımının bir sürümü. Bu formatta daha genel uygulanabilirliği olabilir. Harika cevap, Rory - teşekkürler!

$.fn.visibleHeight = function() {
    var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop;
    scrollTop = $(window).scrollTop();
    scrollBot = scrollTop + $(window).height();
    elTop = this.offset().top;
    elBottom = elTop + this.outerHeight();
    visibleTop = elTop < scrollTop ? scrollTop : elTop;
    visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
    return visibleBottom - visibleTop
}

Aşağıdakilerle çağrılabilir:

$("#myDiv").visibleHeight();

jsFiddle


2
Pencerenin büyüdüğü ve bloğun sığabileceği durumda çalışmayın. Bu yüzden blok yüksekliğini sıfırlamamız gerekiyor: $ (this) .css ('height', ''); jsfiddle.net/b5DGj/144
Max Koshel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.