Upozorňujeme, že tento blogový príspevok bol publikovaný v júni 2015, takže v závislosti od toho, kedy ho čítate, môžu byť niektoré časti zastarané. Bohužiaľ, nemôžem tieto príspevky vždy udržiavať úplne aktuálne, aby som zabezpečil presnosť informácií.
- Moja testovacia stránka
- Pochopenie predvoleného správania
- Pochopenie toho, čo robí pravidlo CSS "-webkit-overflow-scrolling"
- Používateľ musí počkať, kým sa efekt gumičky skončí
- Ako zabrániť, aby sa pozadie stránky posúvalo
- Ako zabrániť nadmernému posúvaniu na pozadie stránky
- Ako zabrániť overscrollu na pozadie stránky
- Zdrojový kód celej stránky
Aby som vyriešil nedávny problém so posúvaním v Safari na iOS, bol som nútený vytvoriť si vlastnú jednoduchú testovaciu stránku a potom použiť všetky informácie a kombinácie, ktoré som našiel na internete, aby som sa pokúsil problém vyriešiť.
Nižšie nájdete stručný prehľad toho, čo som počas tohto procesu zistil.
Moja testovacia stránka
Moja testovacia stránka bola celkom jednoduchá. Skladala sa z fiktívnych údajov v statickom div-e, ktorý predstavuje "stránku", spolu s fixným divom, ktorý predstavuje prekryté "menu" nad stránkou, ako to vyzerá.
Úplný zdrojový kód tejto stránky nájdete na konci tohto blogového príspevku.
Pochopenie predvoleného správania
Prvým krokom bolo zistiť, aké je predvolené správanie Safari na iOS. Najvýraznejším zistením bolo, že keď ste sa posunuli až na spodok ponuky, telo stránky vykazovalo 'gumový efekt' – pevne zakódovaná vlastnosť v Safari.
Stalo sa to aj pri posúvaní na úplný vrchol ponuky.
Avšak prvým problémom, ktorý som si všimol, bolo, že ak neustále posúvate až na samotný vrchol alebo spodok stránky, Safari začne zobrazovať chyby pri vykresľovaní na pozadí stránky aj v menu.
Nie som si istý, prečo, ale mám podozrenie, že to má čo do činenia s funkciou gumového efektu.
Pochopenie toho, čo robí pravidlo CSS "-webkit-overflow-scrolling"
Ďalším krokom bolo aplikovať pravidlo CSS -webkit-overflow-scrolling na menu, ktoré umožňuje plynulé posúvanie s efektom momentu.
Ako je uvedené na obrázku nižšie, posúvanie pokračuje aj po tom, čo potiahnem prstom.
Ale pri posúvaní na úplný vrchol alebo spodok sa tiež objaví efekt gumového pásu, ako je uvedené nižšie.
Používateľ musí počkať, kým sa efekt gumičky skončí
Počas môjho testovania som si tiež všimol, že kým prebieha efekt pružného natiahnutia, používateľ nemôže prepnúť zameranie na iný prvok, kým sa animácia úplne nedokončí.
V nasledujúcom príklade najprv posúvam pozadie stránky a potom rýchlo skúšam posúvať menu, no napokon skončím pri tom, že naďalej posúvam pozadie stránky.
Avšak ak chvíľu počkám, kým efekt skončí, môžem potom začať posúvať menu.
Ako zabrániť, aby sa pozadie stránky posúvalo
Počas testovania som si tiež všimol, že zatiaľ čo prebieha efekt elastického pásu, používateľ nemôže presunúť zameranie na iný prvok, kým sa animácia úplne neskončí.
Na základe tejto odpovede zo Stack Overflow môžete zabezpečiť, že prvky s disable-scrolling nebudú vykonávať svoju predvolenú akciu pri udalosti touchmove.
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();
}
};
A potom pridajte triedu disable-scrolling na div stránky:
<div class="page disable-scrolling">
Takto to funguje do určitej miery, ale podrobnejšie testy ukazujú, že pozadie stránky sa môže ešte občas posúvať, keď dosiahnete úplný vrchol alebo spodok ponuky.
Ako zabrániť nadmernému posúvaniu na pozadie stránky
Použitím tohto riešenia je možné zabrániť „overscrollu“. To znamená, že keď sa prvok dostane až na svoj úplný horný alebo dolný okraj, posúvanie sa nebude presúvať do tela stránky.
V dôsledku toho sa telo stránky nedokáže posúvať, čo tiež zabraňuje vzniku efektu pružiny.
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"));
Čo tento kúsok JavaScriptu robí, je, že zabraňuje prvku dostať sa až na horný ani spodný okraj tým, že ho udržiava len 1 pixel od okrajov.
Ak posúvanie nikdy nedosiahne absolútnu hornú ani dolnú hranicu, overscroll sa nemôže vyskytnúť.
Ako zabrániť overscrollu na pozadie stránky
Ak chcete odstrániť efekt pružného posúvania z ponuky — buď zo estetických dôvodov, alebo preto, že v mojom prípade spôsoboval ďalšie problémy s vykresľovaním — jednoducho odstráňte pravidlo CSS -webkit-overflow-scrolling.
Avšak, ako vidíte nižšie, aj vy stratíte plynulosť pri posúvaní.
Zdrojový kód celej stránky
Tu je kompletný zdrojový kód tejto stránky.
<!-- 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>