Özel kaydırma çubukları son derece nadirdir ve bu durum büyük ölçüde kaydırma çubukları, web'de birçok kullanıcı tarafından sabit tutulamaz (Sana bakıyorum, tarih seçici). Kendi JavaScript'inizi oluşturmak için JavaScript kullanabilirsiniz, ancak bu pahalı ve ve takılabilir. Bu makalede, proje yaşam döngüsü boyunca standart olmayan CSS matrislerinden yararlanarak Kaydırma sırasında JavaScript, yalnızca bazı kurulum kodları vardır.
Özet
Küçük şeyler sizin için önemli değil mi? Tek yapmanız gereken Nyan kedi demosu kitaplığını edinmek ister misiniz? Demonun kodunu şurada bulabilirsiniz: GitHub deposu.
LAM;WRA (Uzun ve matematiksel; yine de okuyacak)
Bir süre önce bir paralaks kaydırıcısı geliştirdik ( ? Gerçekten iyi, zaman ayırmaya değer!). CSS 3D kullanarak öğeleri geri aktararak öğeler gerçek kaydırma hızımızdan daha yavaş hareket etmiştir.
Özet
Paralaks kaydırma çubuğunun çalışma şeklini özetleyerek başlayalım.
Animasyonda gösterildiği gibi, öğeleri iterek paralaks efektini 3D uzayda Z ekseni boyunca "geriye doğru". Dokümanda kaydırmak çevirisini görebilirsiniz. Örneğin, 100 piksel gibi aşağı kaydırdığımızda, öğesi, 100 piksel yukarıya çevrilir. Bu tüm öğeler için geçerlidir, hatta "daha eskideki" kitleler olabilir. Ancak web'den daha uzakta çünkü ekranda gözlemlenen hareketleri 100 pikselden az olur ve böylece paralaks efektini ortaya koyabilir.
Elbette bir öğeyi tekrar uzaya taşımak da onun daha küçük görünmesini sağlar. Bunu düzeltmek için öğeyi tekrar yukarı doğru ölçeklendiririz. Arkadaş Bitkiler projesinin ilk projemizin paralaks kaydırma çubuğu tüm detayları tekrarlamayacağım.
0. Adım: Ne yapmak istiyoruz?
Kaydırma çubukları. İşte bunu geliştireceğiz. Peki hiç düşündünüz mü merak ediyor musunuz? Kesinlikle yapmadım. Kaydırma çubukları, Şu anda mevcut içeriğin ne kadarının görünür durumda olduğu ve ne kadar ilerleme kaydedildiğini siz de düşünmüşsünüzdür. Ekranı aşağı kaydırdığınızda kaydırma çubuğu da projenin sonuna doğru ilerleme kaydettiğinizi gösterir. Tüm içerikler uygunsa görüntü alanında kaydırma çubuğu genellikle gizlidir. İçerik, görüntü alanının yüksekliğinin 2 katıysa kaydırma çubuğu, görüntü alanının yüksekliğinin 1⁄2'sini kaplar. 3 kat yüksekliğe sahip içerik görüntü alanı, kaydırma çubuğunu görüntü alanının 1⁄3'üne ölçeklendirir. Bu şekilde kalıbı görürsünüz. Kaydırmak yerine kaydırma çubuğunu tıklayıp sürükleyerek de yardımcı olur. Bu, göze çarpmayan bir kişi için şaşırtıcı derecede büyük bir buna benzer. Gelin, teker teker savaşalım.
1. Adım: Ters konulma
Tamam, CSS 3D kullanarak öğelerin kaydırma hızından daha yavaş hareket etmesini sağlayabiliriz ana hatlarıyla açıklandığı gibi dönüştürülür. Aynı zamanda yönünüzü bulmak mı istiyorsunuz? Görünüşe göre yapabiliriz. Kullanıcılardan farklı bir alan mükemmel, özel kaydırma çubuğu. Bunun nasıl işlediğini anlamak için bir konuyu ele almalıyız: CSS 3D ile ilgili temel bilgileri edineceğim.
Matematiksel açıdan herhangi bir perspektif projeksiyonunu elde etmek için büyük ihtimalle homojen koordinatlar kullanmanız gerekir. Bunların ne olduğunu ve neden işe yaradığını ayrıntılı olarak açıklamayacağım, ama Bunlar, w adlı ek bir dördüncü koordinatla birlikte 3D koordinatlar gibidir. Bu perspektif bozulması isteniyorsa koordinat değeri 1 olmalıdır. Biz b'nin ayrıntılarıyla ilgili olarak endişelenmenize gerek yoktur; çünkü 1 dışında bir değerdir. Dolayısıyla, tüm noktalar artık 4 boyutlu vektörlerden alınır [x, y, z, w=1] ve sonuç olarak matrislerde olması gerekir.
CSS'nin
kullanarak bir dönüştürme özelliğinde kendi 4x4 matrislerinizi tanımlamaktır.
matrix3d()
işlevi. matrix3d
, 16 bağımsız değişken alır (çünkü matris
4x4) biçimindedir). Bu fonksiyonu kullanarak
çevirmeleri, çevirmeleri vb. manuel olarak belirtme
w koordinatını karıştırabilir!
matrix3d()
özelliğini kullanabilmek için 3D bir bağlama ihtiyacımız var. Sonuçta
3D bağlamda perspektif bozulması ve 3D içeriğe
koordinatlar arasında olacaktır. 3D bağlam oluşturmak için,
perspective
ve içindeki bazı öğeler, yeni Studio'da dönüştürülecek.
3D alan oluşturdu. Örneğin,
örnek:
Perspektif kapsayıcısının içindeki öğeler, CSS motoru tarafından işlenir şu şekildedir:
- Bir öğenin her bir köşesini (köşeyi) homojen koordinatlara dönüştürün
[x,y,z,w]
, perspektif kapsayıcısına göre. - Öğenin tüm dönüşümlerini sağdan sola matris olarak uygulayın.
- Perspektif öğesi kaydırılabiliyorsa bir kaydırma matrisi uygulayın.
- Perspektif matrisini uygulayın.
Kaydırma matrisi, y ekseni boyunca uzanan bir çeviridir. Aşağıya kayarak 400 piksel olarak ayarlamak için tüm öğelerin 400 piksel x yukarıya taşınması gerekir. Perspektif matrisi noktaları kaybolma noktasına 3D'de daha da geri "çeken" matris ne kadar iyi olduğunu ortaya koyabilir. Bu da, öğeler bir araya getirildiğinde öğelerin daha küçük görünmesinin bu nedenle çeviri sırasında "daha yavaş hareket ediyor". Dolayısıyla, bir öğe geri itilirse 400 piksellik bir çeviri, öğenin ekranda yalnızca 300 piksel hareket ettirin.
Tüm ayrıntıları öğrenmek istiyorsanız CSS'ye ilişkin spesifikasyon ancak bu makalede örnek olarak, her bir dönüşüm işleminde daha fazla bilgi edineceksiniz.
Kutumuz, perspective
için p değerine sahip bir perspektif kabının içinde
ve kapsayıcının kaydırılabilir olduğunu ve kapsayıcının
n piksel.
İlk matris perspektif matrisi, ikinci matris ise kaydırmadır. matristir. Özetlemek gerekirse: Kaydırma matrisinin işi, bir öğeyi yukarıya taşımak aşağı kaydırılıyor. Bu nedenle eksi işareti vardır.
Ancak kaydırma çubuğumuz için tam tersini istiyoruz. Öğemizin
aşağıya doğru aşağı kaydırabilirsiniz. İpuçlarını şu şekilde kullanabiliriz:
Kutumuzun köşelerinin w koordinatını ters çevirme. w koordinatı
-1, tüm çeviriler ters yönde gerçekleşir. Peki, bunu nasıl
bu mu? CSS motoru, kutumuzun köşelerini üçgen şeklinde
ve w'yı 1'e ayarlar. matrix3d()
ile dikkatleri üzerinize çekin!
.box {
transform:
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
);
}
Bu matrisin amacı w'yu eksiltmektir. CSS motoru,
her köşeyi [x,y,z,1]
biçiminde bir vektöre dönüştürürse matris
[x,y,z,-1]
biçimine dönüştürebilirsiniz.
Öğe dönüşümümüzün etkisini göstermek için bir ara adım listeledim matristir. Matris matematiğiyle ilgili olarak kendinizi rahat hissetmiyorsanız sorun değil. Eureka son satırda, n'nin kaydırma ofsetini y'mize ekleyerek koordinasyonunu kullanabilirsiniz. Öğe aşağı doğru çevrilir aşağı kaydırdığımızda da görünür.
Ancak bu matrisi örnek, öğe görüntülenmez. Çünkü CSS spesifikasyonu için w < olan tepe noktası 0 değeri, öğenin oluşturulmasını engeller. Z kuşağından koordinat şu anda 0'dır ve p değeri 1'dir; w ise -1 olur.
Neyse ki z'nin değerini seçebiliriz. w=1'in elde edilmesini sağlamak için kullanarak z = -2 olarak ayarlayın.
.box {
transform:
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
)
translateZ(-2px);
}
Bakın, kutusu geri döndü!
2. Adım: Harekete geçirin
Kutumuz oldu ve bu kutu hiç kutucuk olmasaydı da dönüşür. Perspektif kapsayıcısı şu anda kaydırılamadığı için yapamıyoruz. ancak öğemizin başka yöne gideceğini biliyoruz kaydırıldı. Kapsayıcıyı kaydıralım, değil mi? Yalnızca yer kaplayan ayırıcı öğe:
<div class="container">
<div class="box"></div>
<span class="spacer"></span>
</div>
<style>
/* … all the styles from the previous example … */
.container {
overflow: scroll;
}
.spacer {
display: block;
height: 500px;
}
</style>
Şimdi de kutuyu kaydırın! Kırmızı kutu aşağı hareket eder.
3. Adım: Bir beden belirleyin
Sayfa aşağı kaydırıldığında aşağı hareket eden bir öğemiz vardır. İşte zor olan yardımcı olabilir. Şimdi kaydırma çubuğuna benzer bir stil belirlemeli etkileşimli hale getirmektir.
Kaydırma çubuğu genellikle bir "parmak" ve "parça"dan oluşur ancak parça her zaman görünür olması gerekir. Başparmak yüksekliği, başparmağının yüksekliği ile doğru orantılıdır. görünür olduğundan emin olun.
<script>
const scroller = document.querySelector('.container');
const thumb = document.querySelector('.box');
const scrollerHeight = scroller.getBoundingClientRect().height;
thumb.style.height = /* ??? */;
</script>
scrollerHeight
, kaydırılabilir öğenin yüksekliğidir,
scroller.scrollHeight
, kaydırılabilir içeriğin toplam yüksekliğidir.
scrollerHeight/scroller.scrollHeight
, içerikle ilgili olup
görünür. Başparmağın kapladığı dikey alanın oranı
Görünür içeriğin oranı:
<script>
// …
thumb.style.height =
scrollerHeight * scrollerHeight / scroller.scrollHeight + 'px';
// Accommodate for native scrollbars
thumb.style.right =
(scroller.clientWidth - scroller.getBoundingClientRect().width) + 'px';
</script>
Başparmak boyutu iyi görünüyorsa ama çok hızlı ilerliyor. Burada tekniğimizi paralaks kaydırıcısı. Öğeyi daha geriye taşırsak öğe, daha yavaş kaydırır. Bu boyutu büyüterek düzeltebiliriz. Ama ne kadar çaba göstermeli geri alabilir miyiz? Haydi tahmin edelim, matematik problemi çözelim. Bu son defa, sözü.
En önemli bilgi de şu: Parmağınızın alt kenarını
tamamen kaydırıldığında kaydırılabilir öğenin alt kenarıyla hizalanacak
aşağı tüketim. Başka bir deyişle: Sayfayı kaydırdıysak
Resmimiz scroller.scrollHeight - scroller.height
piksel olsun
scroller.height - thumb.height
tarafından çevrildi. Kaydırma çubuğunun her pikseli için
bir pikselin
bir kısmını hareket ettirmesini istiyorsanız:
Bu, bizim ölçeklendirme faktörümüz. Şimdi ölçeklendirme faktörünü
paralaks kaydırmada yaptığımız gibi, z ekseninde çeviri
makalesine göz atın. Kaynak:
Özelliklerdeki ilgili bölüme dikkat edin:
Ölçeklendirme faktörü p/(p − z) değerine eşittir. Bu denklemi, z'den 'e doğru giderebiliriz.
başparmağımızı z ekseni boyunca ne kadar çevirmemiz gerektiğini
ölçebiliriz. Ama devam et
w koordinatı kurcalamalarımız nedeniyle, bir dili
z boyunca ek -2px
. Ayrıca, bir öğenin dönüşümlerinin uygulandığını
anlamına gelir. Özel matrisinizden önceki tüm çeviriler,
Ancak özel matristen sonraki tüm çeviriler tersine çevrilir. Haydi
bunu kodla!
<script>
// ... code from above...
const factor =
(scrollerHeight - thumbHeight)/(scroller.scrollHeight - scrollerHeight);
thumb.style.transform = `
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
)
scale(${1/factor})
translateZ(${1 - 1/factor}px)
translateZ(-2px)
`;
</script>
Bir kaydırma çubuğunu kullanabilirsiniz. Bu yalnızca bir DOM öğesi. İstediğimiz gibi şekillendirebiliriz. Projeye ilişkin açısından en önemli şey başparmağınızın bu kişilere yanıt vermesidir. ve sürükleyebilirsiniz. Çünkü birçok kullanıcı kaydırma çubuğuyla bu şekilde etkileşimde bulunmaya alışkın. Bu blog yayınını daha da uzatmamak adına bu konudaki detaylıca değineceğiz. Şu bölüme göz atın: kitaplık kodu ayrıntılara göz atın.
Peki ya iOS?
Ah, eski arkadaşım iOS Safari. Paralaks kaydırmada olduğu gibi
bahsedeceğim. Bir öğe üzerinde kaydırdığımız için
-webkit-overflow-scrolling: touch
, ancak bu, 3D düzleştirmeye ve tüm
kaydırma efekti çalışmayı durdurur. Bu sorunu paralaks kaydırıcıda çözdük
iOS Safari'yi tespit edip geçici çözüm olarak position: sticky
'ı kullanarak ve
Burada da tam olarak aynı şeyi yapacağız. Şu bölüme göz atın:
paralaks oluşturma makalesi
dokunun.
Tarayıcının kaydırma çubuğuna ne olacak?
Bazı sistemlerde kalıcı, yerel bir kaydırma çubuğuyla uğraşmak zorundayız.
Önceden kaydırma çubuğu gizlenemez (
standart olmayan sözde seçici) kullanabilirsiniz.
Dolayısıyla, bunu gizlemek için (matematiksiz) birtakım bilgisayar korsanlarına başvurmamız gerekiyor. İçerikleri
kaydırma öğesini overflow-x: hidden
içeren bir kapsayıcıda açın ve
kaydırma öğesi, kapsayıcıdan daha geniştir. Tarayıcının yerel kaydırma çubuğu
artık görüntü dışında.
Fin
Hepsini bir araya getirdiğimizde, artık muhteşem bir özel tasarım oluşturabiliriz. kaydırma çubuğunu kullanın (örneğin, Nyan kedi demosu.
Nyan kedisini görmüyorsanız, bulduğumuz ve dosyaladığımız bir hata (Nyan kedisinin görünmesi için başparmağını tıklayın). Chrome, gereksiz çalışmalardan kaçınmada gerçekten çok iyidir boyama veya animasyon gibi bir şeyler hazırlayabilirsiniz. Kötü haber şu ki matris kurnazlıkları, Chrome'un Nyan kedi GIF'inin aslında ekran dışı olduğunu düşünmesine neden oluyor. Bu sorunun kısa süre içinde düzeltileceğini umuyoruz.
İşte oldu. Çok emek harcamıştım. Tamamını okuduğunuz için sizi tebrik ederim şey. Bu biraz işe yarayacağını bilmenin bir yolu yoktur ve muhtemelen çabaya değmez Ancak özelleştirilmiş kaydırma çubuğunun bu deneyimin önemli bir parçası olduğu durumlar hariç. Ama mümkün olduğunu bilmek güzel, değil mi? Bir şeyi yapmanın zor olduğu düşünüldüğünde, özel kaydırma çubuğu, CSS tarafında yapılacak işler olduğunu gösterir. Endişelenmeyin! Gelecekte, Houdini AnimationWorklet, bunun gibi mükemmel kaydırma bağlantılı efektleri çok daha kolay hale getiriyor.