IntersectionObservers'lar, gözlemlenen bir öğe tarayıcının görüntü alanına girdiğinde veya buradan çıktığında sizi bilgilendirir.
DOM'nizdeki bir öğenin görünür görünüm alanına girdiğini izlemek istediğinizi varsayalım. Resimleri tam zamanında yüklemek veya kullanıcının belirli bir reklam banner'ına gerçekten baktığını öğrenmek için bu yöntemi uygulayabilirsiniz. Bu işlemi, kaydırma etkinliğini bağlayarak veya periyodik bir zamanlayıcı kullanarak ve söz konusu öğede getBoundingClientRect()
çağrısı yaparak gerçekleştirebilirsiniz.
Ancak bu yaklaşım, getBoundingClientRect()
öğesine yapılan her çağrı tarayıcıyı tüm sayfayı yeniden düzenlemeye zorladığı ve web sitenizde önemli ölçüde olumsuz etki yaratacağı için bu yaklaşım oldukça yavaştır. Sitenizin bir iframe içinde yüklendiğini bildiğiniz ve kullanıcının bir öğeyi ne zaman görebileceğini bilmek istiyorsanız önemli konular neredeyse imkansızdır. Tek Kaynaklı Model ve tarayıcı, iframe'i içeren web sayfasından hiçbir veriye erişmenize izin vermez. Bu, örneğin iframe'ler kullanılarak sıklıkla yüklenen reklamlar için yaygın bir sorundur.
IntersectionObserver
, bu görünürlük testini daha verimli hale getirmek amacıyla tasarlanmıştır ve tüm modern tarayıcılara sunulmuştur. IntersectionObserver
, gözlemlenen bir öğe tarayıcının görüntü alanına girdiğinde veya bu alandan çıktığında sizi bilgilendirir.
IntersectionObserver
nasıl oluşturulur?
API oldukça küçüktür ve en iyi açıklaması için aşağıdaki örnekler verilebilir:
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, öğe hem kısmen görünüme girdiğinde hem de görüntü alanından tamamen çıktığında geri çağırma işleminiz çağrılır.
Birden çok öğeyi gözlemlemeniz gerekiyorsa observe()
öğesini birden fazla kez çağırarak aynı IntersectionObserver
örneğini kullanan birden fazla öğeyi gözlemlemeniz hem mümkündür hem de tavsiye edilir.
IntersectionObserverEntry
nesne dizisi olan geri çağırmanıza bir entries
parametresi aktarılır. Bu tür her nesne, gözlemlenen öğelerinizden biri için güncellenmiş kesişim verilerini 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ısı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 kısmının görünür olduğunu etkili bir şekilde bildirir. intersectionRatio
yakından alakalıdır ve öğenin ne kadarının görünür olduğunu belirtir. Elinizin altındaki bu bilgiler sayesinde artık öğeleri ekranda görünmeden önce tam zamanında yükleme gibi özellikleri uygulayabilirsiniz. Hem de verimli bir şekilde.
IntersectionObserver
'ler verilerini eşzamansız olarak yayınlar ve geri çağırma kodunuz ana iş parçacığında çalışır. Buna ek olarak spesifikasyon, IntersectionObserver
uygulamalarının requestIdleCallback()
kullanması gerektiğini de belirtir. Bu, sağladığınız geri çağırmanın düşük öncelikli olduğu ve boşta kalma süresinde tarayıcı tarafından yapılacağı anlamına gelir. Bu bilinçli bir tasarım kararıdır.
Kayan div'ler
Bir öğenin içinde kaydırmayı çok sevmem ama yargılamak için burada değilim ve IntersectionObserver
de değil. options
nesnesi, kök dizininiz olarak görüntü alanına bir alternatif tanımlamanızı sağlayan bir root
seçeneği alır. root
öğesinin gözlemlenen tüm öğelerin üst öğesi olması gerektiğini unutmayın.
Her şeyi kesiştirin!
Hayır Kötü geliştirici! Bu, kullanıcınızın CPU döngülerinin bilinçli bir şekilde kullanılması anlamına gelmez. Bir sonsuz kaydırma aracını örnek olarak ele alalım: Bu senaryoda, DOM'ye koruyucuların eklenmesi ve bunların gözlemlenmesi (ve geri dönüştürülmesi) kesinlikle önerilir. Sonsuz kaydırma çubuğundaki son öğeye yakın bir koruyucu eklemeniz gerekir. Bu koruyucu görüntülendiğinde, verileri yüklemek, sonraki öğeleri oluşturmak, bunları DOM'ye eklemek ve gözetleyiciyi uygun şekilde yeniden konumlandırmak için geri çağırma işlevini kullanabilirsiniz. Koruyucuyu uygun şekilde geri dönüştürürseniz observe()
numarasına ek bir çağrı yapılmasına gerek yoktur. IntersectionObserver
çalışmaya devam eder.
Daha fazla güncelleme lütfen
Daha önce belirtildiği gibi, geri çağırma, gözlemlenen öğe kısmen görünüme girdiğinde bir kez ve görüntü alanından ayrıldığında bir kez daha tetiklenir. Bu şekilde IntersectionObserver
, "X öğesi görüntüleniyor mu?" sorusuna yanıt vermenizi sağlar. Ancak bazı durumlarda bu yeterli olmayabilir.
Bu noktada threshold
seçeneği devreye girer. Bir intersectionRatio
eşik dizisi tanımlamanıza olanak tanır. intersectionRatio
bu değerlerden birini her aştığında geri çağırmanız çağrılır. threshold
için varsayılan değer olan [0]
, varsayılan davranışı açıklar. threshold
değerini [0, 0.25, 0.5, 0.75, 1]
olarak değiştirirsek öğenin fazladan dörtte biri görünür olduğunda bildirim alırsınız:
Başka seçenek var mı?
Şimdilik yukarıda listelenenler dışında yalnızca bir seçenek bulunmaktadır. rootMargin
, kök için kenar boşluklarını belirtmenize olanak tanır. Böylece, kesişimler için kullanılan alanı etkili bir şekilde büyütebilir veya küçültebilirsiniz. Bu kenar boşlukları, sırasıyla üst, sağ, alt ve sol kenar boşluğunu belirten CSS stili bir dize (á la "10px 20px 30px 40px"
) kullanılarak belirtilir. Özetle, IntersectionObserver
seçenekleri struct 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>
büyüsü
IntersectionObserver
'lar, özel olarak reklam hizmetleri ve sosyal ağ widget'ları göz önünde bulundurularak tasarlanmıştır. Bu özellikler, sıklıkla <iframe>
öğelerini kullanır ve görünümde olup olmadıklarını bilmek yararlı olabilir. <iframe>
, öğelerinden birini gözlemlerse hem <iframe>
hem de <iframe>
öğesini içeren pencerenin kaydırılması uygun zamanlarda geri çağırmayı tetikler. Ancak ikinci durumda rootBounds
, kaynaklar arasında veri sızıntısını önlemek için null
olarak ayarlanır.
IntersectionObserver
ne hakkında değil?
Unutulmaması gereken bir nokta, IntersectionObserver
özelliğinin kasıtlı olarak ne piksel mükemmeli ne de düşük gecikme süresi olduğudur. Kaydırmaya dayalı animasyonlar gibi işlemlerin uygulanması için bu tür öğelerin kullanılması kesinlikle başarısız olur. Çünkü, kesin şekilde ifade etmek gerekirse veriler, kullanmaya başladığınız zamana kadar güncelliğini yitirmiş olacaktır. IntersectionObserver
için orijinal kullanım alanları hakkında daha fazla bilgiyi açıklayıcıda bulabilirsiniz.
Geri aramada ne kadar iş yapabilirim?
Shorts ve Tatlı: Geri çağırma için çok fazla zaman harcamak uygulamanızın gecikmesine neden olur. Tüm yaygın uygulamalar geçerlidir.
Çıkın ve öğelerinizi kesiştirin
Tüm modern tarayıcılarda mevcut olduğundan IntersectionObserver
için tarayıcı desteği iyidir. Gerekirse eski tarayıcılarda bir çoklu dolgu kullanılabilir ve WICG'nin deposunda bulunabilir. Elbette, yerel bir uygulamanın size sağlayacağı bu çoklu dolguyu kullandığınızda performans avantajlarından yararlanamazsınız.
IntersectionObserver
ürününü kullanmaya hemen başlayabilirsiniz. Karşılaştığınız sorunu bizimle paylaşın.