IntersectionObserver's geliyor

IntersectionObserver'lar, gözlemlenen bir öğenin tarayıcının görüntü alanına ne zaman girdiğini veya çıktığını bildirir.

Browser Support

  • Chrome: 51.
  • Edge: 15.
  • Firefox: 55.
  • Safari: 12.1.

Source

DOM'unuzdaki bir öğenin görünür görüntü alanına ne zaman girdiğini izlemek istediğinizi varsayalım. Resimleri tam zamanında geç yüklemek istediğinizde veya kullanıcının belirli bir reklam banner'ına gerçekten bakıp bakmadığını öğrenmeniz gerektiğinde bu yöntemi kullanabilirsiniz. Bunu yapmak için kaydırma etkinliğini bağlayabilir veya periyodik bir zamanlayıcı kullanıp ilgili öğede getBoundingClientRect() yöntemini çağırabilirsiniz.

Ancak bu yaklaşım, getBoundingClientRect() için yapılan her çağrı tarayıcıyı tüm sayfayı yeniden düzenlemeye zorladığından ve web sitenizde önemli ölçüde takılmaya neden olacağından son derece yavaştır. Sitenizin bir iFrame içinde yüklendiğini bildiğinizde ve kullanıcının bir öğeyi ne zaman görebileceğini öğrenmek istediğinizde işler neredeyse imkansız hale gelir. Tek kaynak modeli ve tarayıcı, iFrame'i içeren web sayfasındaki verilere erişmenize izin vermez. Bu, örneğin genellikle iframe'ler kullanılarak yüklenen reklamlarda sık karşılaşılan bir sorundur.

IntersectionObserver, bu görünürlük testini daha verimli hale getirmek için tasarlanmıştır ve tüm modern tarayıcılarda kullanılabilir. IntersectionObserver, gözlemlenen bir öğenin tarayıcının görüntü alanına ne zaman girdiğini veya çıktığını bildirir.

iFrame görünürlüğü

IntersectionObserver oluşturma

API oldukça küçüktür ve en iyi şekilde bir örnekle açıklanabilir:

const io = new IntersectionObserver(entries => {
  console.log(entries);
}, {
  /* Using default options. Details below */
});

// Start observing an element
io.observe(element);

// Stop observing an element
// io.unobserve(element);

// Disable entire IntersectionObserver
// io.disconnect();

IntersectionObserver için varsayılan seçenekler kullanıldığında geri çağırma işleviniz, öğe kısmen görünür hale geldiğinde ve görüntü alanından tamamen çıktığında çağrılır.

Birden fazla öğeyi gözlemlemeniz gerekiyorsa observe() yöntemini birden çok kez çağırarak aynı IntersectionObserver örneğini kullanarak birden fazla öğeyi gözlemlemek hem mümkündür hem de önerilir.

Geri çağırma işlevinize, IntersectionObserverEntry nesnelerinden oluşan bir dizi olan entries parametresi iletilir. Bu tür her nesne, gözlemlenen öğelerinizden biri için güncellenmiş kesişim verileri içerir.

🔽[IntersectionObserverEntry]
    time: 3893.92
    🔽rootBounds: ClientRect
        bottom: 920
        height: 1024
        left: 0
        right: 1024
        top: 0
        width: 920
    🔽boundingClientRect: ClientRect
    // ...
    🔽intersectionRect: ClientRect
    // ...
    intersectionRatio: 0.54
    🔽target: div#observee
    // ...

rootBounds, varsayılan olarak görüntü alanı olan kök öğede getBoundingClientRect() çağrılmasının sonucudur. boundingClientRect, gözlemlenen öğede çağrılan getBoundingClientRect() işlevinin sonucudur. intersectionRect, bu iki dikdörtgenin kesişimidir ve gözlemlenen öğenin hangi bölümünün görünür olduğunu gösterir. intersectionRatio, öğenin ne kadarının görünür olduğunu gösterir ve bu tetikleyiciyle yakından ilişkilidir. Bu bilgiler sayesinde, öğelerin ekranda görünmeden önce tam zamanında yüklenmesi gibi özellikleri uygulayabilirsiniz. Verimli bir şekilde.

Kesişim oranı.

IntersectionObserver'ler verilerini eşzamansız olarak yayınlar ve geri çağırma kodunuz ana iş parçacığında çalışır. Ayrıca spesifikasyonda, IntersectionObserver uygulamalarının requestIdleCallback() kullanması gerektiği belirtilir. Bu, sağladığınız geri çağırma işlevine yapılan çağrının düşük öncelikli olduğu ve tarayıcı tarafından boşta kalma süresi boyunca yapılacağı anlamına gelir. Bu, bilinçli bir tasarım kararıdır.

Kaydırılabilir div'ler

Bir öğenin içinde kaydırma yapmayı pek sevmiyorum ancak burada yargılamak için bulunmuyorum. IntersectionObserver da öyle. options nesnesi, görüntü alanına alternatif olarak kökünüzü tanımlamanıza olanak tanıyan bir root seçeneği alır. root öğesinin, gözlemlenen tüm öğelerin üst öğesi olması gerektiğini unutmayın.

Tüm öğeleri kesiştirin.

Hayır Kötü geliştirici! Bu, kullanıcınızın CPU döngülerinin dikkatli bir şekilde kullanılması değildir. Örnek olarak sonsuz kaydırma özelliğini ele alalım: Bu senaryoda, DOM'a gözetleyiciler eklemek ve bunları gözlemlemek (ve geri dönüştürmek!) kesinlikle önerilir. Sonsuz kaydırıcıdaki son öğeye yakın bir sentinel eklemeniz gerekir. Bu işaretçi görünür hale geldiğinde, verileri yüklemek, sonraki öğeleri oluşturmak, bunları DOM'a eklemek ve işaretçiyi buna göre yeniden konumlandırmak için geri çağırmayı kullanabilirsiniz. Sentinel'i doğru şekilde geri dönüştürürseniz observe() için ek bir çağrı yapmanız gerekmez. IntersectionObserver çalışmaya devam eder.

Sonsuz kaydırma

Daha fazla güncelleme istiyorum

Daha önce de belirtildiği gibi, geri çağırma, gözlemlenen öğe kısmen göründüğünde bir kez, görüntü alanından çıktığında ise bir kez daha tetiklenir. Bu sayede IntersectionObserver, "X öğesi görünümde mi?" sorusuna yanıt verir. Ancak bazı kullanım alanlarında bu yeterli olmayabilir.

threshold seçeneği bu noktada devreye girer. intersectionRatio eşiklerinden oluşan bir dizi tanımlamanıza olanak tanır. intersectionRatio bu değerlerden birini her geçtiğinde geri çağırma işleviniz çağrılır. threshold için varsayılan değer [0]'dir. Bu değer, varsayılan davranışı açıklar. threshold değerini [0, 0.25, 0.5, 0.75, 1] olarak değiştirirsek öğenin her ek çeyreği görünür olduğunda bildirim alırız:

Eşik animasyonu.

Başka seçenekler var mı?

Şu anda yukarıda listelenenlere ek olarak yalnızca bir seçenek daha vardır. rootMargin, kök için kenar boşluklarını belirtmenize olanak tanır. Böylece kesişimler için kullanılan alanı büyütebilir veya küçültebilirsiniz. Bu kenar boşlukları, sırasıyla üst, sağ, alt ve sol kenar boşluğunu belirten "10px 20px 30px 40px" gibi bir CSS stili dizesi kullanılarak belirtilir. Özetlemek gerekirse IntersectionObserver options yapısı aşağıdaki seçenekleri sunar:

new IntersectionObserver(entries => {/* … */}, {
  // The root to use for intersection.
  // If not provided, use the top-level document's viewport.
  root: null,
  // Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
  // If an explicit root element is specified, components may be percentages of the
  // root element size.  If no explicit root element is specified, using a
  // percentage is an error.
  rootMargin: "0px",
  // Threshold(s) at which to trigger callback, specified as a ratio, or list of
  // ratios, of (visible area / total area) of the observed element (hence all
  // entries must be in the range [0, 1]).  Callback will be invoked when the
  // visible ratio of the observed element crosses a threshold in the list.
  threshold: [0],
});

<iframe> sihir

IntersectionObserver, özellikle reklam hizmetleri ve sosyal ağ widget'ları göz önünde bulundurularak tasarlanmıştır. Bu widget'lar, sık sık <iframe> öğelerini kullanır ve görünür olup olmadıklarını bilmekten yararlanabilir. Bir <iframe>, öğelerinden birini gözlemlerse hem <iframe> öğesinin kaydırılması hem de <iframe> öğesini içeren pencerenin kaydırılması, geri çağırmayı uygun zamanlarda tetikler. Ancak ikinci durumda, kaynaklar arasında veri sızıntısını önlemek için rootBounds, null olarak ayarlanır.

IntersectionObserver neyle ilgili değildir?

IntersectionObserver'ın bilinçli olarak ne piksel mükemmelliğinde ne de düşük gecikmeli olduğunu unutmayın. Kaydırmaya bağlı animasyonlar gibi işlemleri uygulamak için bu etkinlikleri kullanmak başarısızlığa mahkumdur. Çünkü veriler, siz kullanana kadar güncelliğini yitirmiş olur. Açıklayıcı, IntersectionObserver için orijinal kullanım alanları hakkında daha fazla bilgi içerir.

Geri çağırmada ne kadar işlem yapabilirim?

Kısa ve öz: Geri çağırmada çok fazla zaman harcamak uygulamanızın gecikmesine neden olur. Tüm yaygın uygulamalar geçerlidir.

Devam edin ve öğelerinizi kesiştirin

IntersectionObserver için tarayıcı desteği iyi düzeydedir. Tüm modern tarayıcılarda kullanılabilir. Gerekirse eski tarayıcılarda bir polyfill kullanılabilir. Bu polyfill, WICG'nin deposunda mevcuttur. Doğal olarak, bu polyfill'i kullanarak yerel bir uygulamanın sağlayacağı performans avantajlarını elde edemezsiniz.

IntersectionObserver uygulamasını hemen kullanmaya başlayabilirsiniz. Bulduğunuz fikirleri bizimle paylaşın.