Imajte na umu da je ova objava na blogu objavljena u lipnju 2015., pa ovisno o tome kada je čitate, određeni dijelovi mogu biti zastarjeli. Nažalost, ne mogu uvijek u potpunosti ažurirati ove objave kako bih osigurao točnost informacija.
- Moja testna stranica
- Razumijevanje zadanog ponašanja
- Razumijevanje što radi CSS pravilo "-webkit-overflow-scrolling"
- Korisnik treba pričekati dok se efekt gumene trake ne završi.
- Kako spriječiti pomicanje stranice u pozadini
- Kako spriječiti prekomjerno skrolanje na pozadinsku stranicu
- Kako spriječiti prekomjerno skrolanje na pozadinsku stranicu
- Izvor cijele stranice
Da bih riješio nedavni problem s pomicanjem u Safariju na iOS-u, morao sam izraditi vlastitu jednostavnu testnu stranicu te primijeniti sve informacije i kombinacije koje sam uspio pronaći na internetu kako bih ga pokušao riješiti.
U nastavku slijedi kratak pregled onoga što sam otkrio tijekom ovog procesa.
Moja testna stranica
Moja testna stranica bila je prilično jednostavna. Sastojala se od lažnih podataka u statičkom div elementu koji predstavlja 'stranicu', uz fiksni div koji predstavlja preklopni 'meni' iznad stranice, kao što je prikazano ovdje.
Cijeli izvorni kod stranice možete pronaći na dnu ovog blog posta.
Razumijevanje zadanog ponašanja
Prva stvar koju sam učinio/la bila je pokušati razumjeti zadano ponašanje Safarija na iOS-u. Najvažnije zapažanje bilo je da kada se pomaknete do dna izbornika, tijelo stranice pokazalo je 'efekt elastičnog povlačenja' – ugrađena značajka u Safariju.
Isto se dogodilo i kad sam se pomaknuo do samog vrha izbornika.
Međutim, prvi problem koji sam primijetio je da ako se neprekidno pomičete do samog vrha ili dna, Safari počinje prikazivati grafičke pogreške u pozadini stranice i u izborniku.
Nisam siguran zašto, ali pretpostavljam da to ima veze sa značajkom elastične trake.
Razumijevanje što radi CSS pravilo "-webkit-overflow-scrolling"
Sljedeća stvar koju sam napravio bila je primijeniti CSS pravilo -webkit-overflow-scrolling na izbornik, koje omogućuje pomicanje temeljem momentuma.
Kao što je prikazano na slici ispod, pomicanje se nastavlja čak i nakon što prevučem prstom.
Ali pri tome dodaje i elastični efekt pri pomicanju do samog vrha ili dna, kao što je prikazano u nastavku.
Korisnik treba pričekati dok se efekt gumene trake ne završi.
Tijekom testiranja primijetio sam da, dok je efekt elastičnog odziva u tijeku, korisnik ne može prebaciti fokus na drugi element sve dok animacija potpuno ne završi.
U donjem primjeru najprije pomičem stranicu u pozadini, a zatim brzo pokušavam pomaknuti izbornik, ali na kraju nastavim pomicanjem same pozadine.
Međutim, ako pričekam trenutak da se učinak završi, tada mogu početi skrolati kroz izbornik.
Kako spriječiti pomicanje stranice u pozadini
Tijekom testiranja također sam primijetio da, dok traje efekt elastičnog vraćanja (rubber-band), korisnik ne može premjestiti fokus na drugi element sve dok animacija u potpunosti ne završi.
Na temelju ovog odgovora sa Stack Overflow, možete osigurati da elementi s disable-scrolling ne izvrše zadanu akciju pomicanja kada se aktivira touchmove događaj.
document.ontouchmove = function(event) {
var isTouchMoveAllowed = true,
target = event.target;
while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
};
Zatim primijenite klasu disable-scrolling na div stranice:
<div class="page disable-scrolling">
Ovo nekako funkcionira, ali detaljnija testiranja pokazuju da pozadinska stranica još ponekad može skrolati kada dođete do samog vrha ili dna izbornika.
Kako spriječiti prekomjerno skrolanje na pozadinsku stranicu
Primjenom ovog rješenje, postaje moguće spriječiti „overscrolling“. To znači da kada element bude pomaknut na sam vrh ili dno, scrollanje se ne nastavlja u tijelo stranice.
Kao rezultat toga, tijelo se ne može pomicati, što također sprječava pojavu efekta elastičnog vraćanja.
function removeIOSRubberEffect(element) {
element.addEventListener("touchstart", function() {
var top = element.scrollTop,
totalScroll = element.scrollHeight,
currentScroll = top + element.offsetHeight;
if (top === 0) {
element.scrollTop = 1;
} else if (currentScroll === totalScroll) {
element.scrollTop = top - 1;
}
});
}
removeIOSRubberEffect(document.querySelector(".scrollable"));
Ovaj JavaScript isječak sprječava da se element ikad dosegne do samog vrha ili dna tako što ga drži 1 piksel udaljenim.
Ako položaj skrolanja nikada ne dosegne apsolutni vrh ili dno, prekoračenje skrolanja se ne može dogoditi.
Kako spriječiti prekomjerno skrolanje na pozadinsku stranicu
Ako želite ukloniti elastični efekt izbornika — bilo iz estetskih razloga ili jer je, kao u mom slučaju, uzrokovao dodatne probleme pri renderiranju — jednostavno uklonite CSS pravilo -webkit-overflow-scrolling.
Međutim, kao što možete vidjeti ispod, gubite i taj osjećaj glatkog pomicanja.
Izvor cijele stranice
Evo cijelog izvornog koda stranice.
<!-- License MIT, Author Special Agent Squeaky (specialagentsqueaky.com) --> <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style> .page{ font-size: 24px; overflow: scroll; } .menu{ position: fixed; top: 0; bottom: 0; left: 0; width: 80%; background: gray; z-index: 1; font-size: 10px; overflow: scroll; /* uncomment to get smooth momentum scroll, but also a rubber band effect */ /*-webkit-overflow-scrolling: touch;*/ } .menu-item{ padding: 10px; background: darkgray; font-size: 24px; } </style>
</head>
<body>
<div class="menu scrollable">
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
</div>
<div class="page disable-scrolling">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged. It was popularised in
the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,
and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</div>
<script>
document.ontouchmove = function(event) {
var isTouchMoveAllowed = true,
target = event.target;
while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
};
function removeIOSRubberEffect(element) {
element.addEventListener("touchstart", function() {
var top = element.scrollTop,
totalScroll = element.scrollHeight,
currentScroll = top + element.offsetHeight;
if (top === 0) {
element.scrollTop = 1;
} else if (currentScroll === totalScroll) {
element.scrollTop = top - 1;
}
});
}
removeIOSRubberEffect(document.querySelector(".scrollable"));
</script>
</body>
</html>