Birden fazla görüntü alanı olduğunu söylesem ne dersiniz?
BRRRRAAAAAAAMMMMMMMMMM
Şu anda kullandığınız görüntü alanı aslında bir görüntü alanı içinde bir görüntü alanıdır.
BRRRRAAAAAAAMMMMMMMMMM
Bazen DOM'un size verdiği veriler, bu ekran alanlarından birini ifade eder ve diğerini ifade etmez.
BRRRRAAAAM… ne dediniz?
Doğru. Şuna göz atın:
Düzen görüntü alanı ve görsel görüntü alanı
Yukarıdaki videoda, bir web sayfasının kaydırıldığı ve iki parmak ucunu yakınlaştırma/uzaklaştırma hareketiyle yakınlaştırıldığı gösterilmektedir. Sağ tarafta ise sayfadaki görüntü alanlarının konumunu gösteren bir mini harita yer almaktadır.
Normal kaydırma sırasında işler oldukça basittir. Yeşil alan, position: fixed
öğelerinin bağlı olduğu düzenleme görüntü alanını gösterir.
İki parmak yakınlaştırma özelliği kullanıldığında işler tuhaflaşıyor. Kırmızı kutu, sayfanın gerçekten görebildiğimiz kısmı olan görsel görüntü alanını temsil eder. Bu görüntü alanı hareket edebilirken position: fixed
öğeleri, düzen görüntü alanına bağlı olarak oldukları yerde kalır. Düzen görüntü alanının sınırında kaydırma yaptığımızda düzen görüntü alanı da sürüklenir.
Uyumluluğu iyileştirme
Maalesef web API'leri, hangi görüntü alanını referans aldıkları açısından tutarlı değildir ve tarayıcılar arasında da tutarlı değildir.
Örneğin, element.getBoundingClientRect().y
, layout görüntü alanındaki ofseti döndürür. Bu harika, ancak genellikle sayfadaki konumu istiyoruz. Bu nedenle şunu yazıyoruz:
element.getBoundingClientRect().y + window.scrollY
Ancak birçok tarayıcı, window.scrollY
için görsel görüntü alanını kullanır. Bu nedenle, kullanıcı parmaklarıyla yakınlaştırdığında yukarıdaki kod bozulur.
Chrome 61, window.scrollY
değerini düzen görüntü alanını referans alacak şekilde değiştirir. Bu nedenle, yukarıdaki kod iki parmak ucunu yakınlaştırma/uzaklaştırma işlemi uygulandığında bile çalışır. Aslında tarayıcılar, tüm konumsal özellikleri düzen görüntü alanına atıfta bulunacak şekilde yavaş yavaş değiştiriyor.
Yeni bir mülk hariç…
Görsel görüntü alanını komut dosyasına gösterme
Yeni API, görsel görüntü alanını window.visualViewport
olarak gösterir. Tarayıcılar arası onay alan bu taslak spesifikasyon, Chrome 61'de kullanıma sunulacak.
console.log(window.visualViewport.width);
window.visualViewport
bize şunları sağlar:
visualViewport tesis |
|
---|---|
offsetLeft
|
Görsel görünüm alanının sol kenarı ile düzen görünüm alanı arasındaki mesafe (CSS piksel cinsinden). |
offsetTop
|
Görsel görüntü alanının üst kenarı ile düzen görüntü alanı arasındaki mesafe (CSS piksel cinsinden). |
pageLeft
|
Görsel görüntü alanının sol kenarı ile dokümanın sol sınırı arasındaki mesafe (CSS piksel cinsinden). |
pageTop
|
Görsel görüntü alanının üst kenarı ile dokümanın üst sınırı arasındaki mesafe (CSS piksel cinsinden). |
width
|
Görsel görünüm alanının CSS piksel cinsinden genişliği. |
height
|
Görsel görünüm alanının CSS piksel cinsinden yüksekliği. |
scale
|
İki parmak ucunu yakınlaştırıp uzaklaştırarak uygulanan ölçek. İçerik, yakınlaştırma nedeniyle iki kat büyükse 2 döndürülür. Bu durum devicePixelRatio 'ten etkilenmez.
|
Ayrıca birkaç etkinlik de vardır:
window.visualViewport.addEventListener('resize', listener);
visualViewport etkinlik |
|
---|---|
resize
|
width , height veya scale değiştiğinde tetiklenir.
|
scroll
|
offsetLeft veya offsetTop değiştiğinde tetiklenir.
|
Demo
Bu makalenin başındaki video visualViewport
kullanılarak oluşturulmuştur. Chrome 61 ve sonraki sürümlerde bu videoyu inceleyebilirsiniz. Mini haritayı görsel görüntü alanının sağ üst köşesine yapıştırmak için visualViewport
kullanılır ve parmak ucuyla yakınlaştırmaya rağmen her zaman aynı boyutta görünmesi için ters ölçek uygulanır.
Dikkat edilmesi gereken noktalar
Etkinlikler yalnızca görsel görüntü alanı değiştiğinde tetiklenir
Bu, açıkça belirtilmesi gereken bir şey gibi görünse de visualViewport
ile ilk oynadığımda beni şaşırtmıştı.
Sayfa düzeni görüntü alanı yeniden boyutlandırılırsa ancak görsel görüntü alanı yeniden boyutlandırılmazsa resize
etkinliği almazsınız. Ancak düzen görüntü alanının, görsel görüntü alanının genişlik/yükseklik değeri değişmeden yeniden boyutlandırılması normal değildir.
Asıl sorun kaydırma işlemidir. Kaydırma gerçekleşirse ancak görsel görüntü alanı düzenleme görüntü alanına göre statik kalırsa visualViewport
üzerinde bir scroll
etkinliği almazsınız. Bu durum oldukça yaygındır. Normal belge kaydırma sırasında görsel görüntü alanı, düzen görüntü alanının sol üst kısmına kilitli kalır. Bu nedenle scroll
, visualViewport
üzerinde tetiklenmez.
pageTop
ve pageLeft
dahil olmak üzere görsel görüntü alanındaki tüm değişiklikler hakkında bilgi edinmek istiyorsanız pencerenin kaydırma etkinliğini de dinlemeniz gerekir:
visualViewport.addEventListener('scroll', update);
visualViewport.addEventListener('resize', update);
window.addEventListener('scroll', update);
Birden fazla dinleyiciyle aynı işi yapma
Pencerede scroll
ve resize
'ü dinlemeye benzer şekilde, sonuç olarak bir tür "güncelleme" işlevi çağırmanız olasıdır. Ancak bu etkinliklerin çoğunun aynı anda gerçekleşmesi yaygın bir durumdur. Kullanıcı pencereyi yeniden boyutlandırırsa resize
etkinleştirilir ancak sıklıkla scroll
da etkinleştirilir. Performansı artırmak için değişikliği birden fazla kez işlemekten kaçının:
// Add listeners
visualViewport.addEventListener('scroll', update);
visualViewport.addEventListener('resize', update);
addEventListener('scroll', update);
let pendingUpdate = false;
function update() {
// If we're already going to handle an update, return
if (pendingUpdate) return;
pendingUpdate = true;
// Use requestAnimationFrame so the update happens before next render
requestAnimationFrame(() => {
pendingUpdate = false;
// Handle update here
});
}
Tek bir update
etkinliği gibi daha iyi bir yöntem olabileceğini düşündüğüm için bu konuda bir özellik sorunu gönderdim.
Etkinlik işleyicileri çalışmıyor
Chrome hatası nedeniyle aşağıdaki işlem çalışmaz:
Hata içeriyor: Etkinlik işleyici kullanıyor
visualViewport.onscroll = () => console.log('scroll!');
Bunun yerine:
Çalışır: Etkinlik işleyici kullanır
visualViewport.addEventListener('scroll', () => console.log('scroll'));
Ofset değerleri yuvarlanır
Bunun başka bir Chrome hatası olduğunu düşünüyorum (umarım öyledir).
offsetLeft
ve offsetTop
değerleri yuvarlanır. Bu nedenle, kullanıcı yakınlaştırdığında değerler oldukça hatalı olur. Bu konuyla ilgili sorunları demoda görebilirsiniz. Kullanıcı yakınlaştırıp yavaşça kaydırdığında mini harita yakınlaştırılmamış pikseller arasında atlar.
Etkinlik oranı yavaş
Diğer resize
ve scroll
etkinlikleri gibi bu etkinlikler de özellikle mobil cihazlarda her karede tetiklenmez. Bu durumu demo sırasında görebilirsiniz. İki parmağınızı yakınlaştırmak için yakınlaştırdığınızda mini harita, görüntü alanına kilitlenmekte sorun yaşar.
Erişilebilirlik
Demoda, kullanıcının iki parmak ucunu yakınlaştırma/uzaklaştırma hareketini önlemek için visualViewport
kullandım. Bu demo için mantıklı olsa da kullanıcının yakınlaştırma isteğini geçersiz kılan herhangi bir işlem yapmadan önce dikkatlice düşünmeniz gerekir.
visualViewport
, erişilebilirliği iyileştirmek için kullanılabilir. Örneğin, kullanıcı yakınlaştırma yapıyorsa dekoratif position: fixed
öğeleri gizleyerek kullanıcının görüş alanından kaldırabilirsiniz. Ancak kullanıcının daha yakından incelemeye çalıştığı bir şeyi gizlemediğinize dikkat edin.
Kullanıcı yakınlaştırdığında bir analiz hizmetine gönderme yapabilirsiniz. Bu sayede, kullanıcıların varsayılan yakınlaştırma düzeyinde zorluk yaşadığı sayfaları belirleyebilirsiniz.
visualViewport.addEventListener('resize', () => {
if (visualViewport.scale > 1) {
// Post data to analytics service
}
});
Hepsi bu kadar! visualViewport
, uyumluluk sorunlarını çözen kullanışlı bir API'dir.