Professionel internetafhængig • Spilentusiast • Teknologiskaber
Professionel internetafhængig • Spilentusiast • Teknologiskaber

Seks ting, jeg lærte om gummibånd-effekten ved rulning i iOS Safari

For at løse et problem med rulning i Safari på iOS blev jeg tvunget til at lave min egen enkle testside!
Denne side er blevet oversat fra engelsk af mine meget motiverede AI-praktikanter for at gøre det nemmere for dig. De er stadig i gang med at lære, så der kan være sluppet et par fejl igennem. For den mest præcise information, se venligst den engelske version.
Hjem Blog Seks ting, jeg lærte om gummibånd-effekten ved rulning i iOS Safari

Bemærk venligst, at dette blogindlæg blev udgivet i juni 2015, så afhængigt af hvornår du læser det, kan visse dele være forældede. Desværre kan jeg ikke altid holde disse indlæg fuldt opdaterede for at sikre, at oplysningerne forbliver nøjagtige.

For at løse et nyt scroll-problem i Safari på iOS var jeg nødt til at oprette min egen enkle testside og derefter anvende al den information og alle de kombinationer, jeg kunne finde på nettet, for at forsøge at løse problemet.

Nedenfor er en kort oversigt over, hvad jeg har fundet ud af i løbet af processen.

Min testside

Min testside var ret enkel. Den bestod af mock-data i et statisk div for at repræsentere 'siden', sammen med et fast div, der viste en overlejret 'menu' over siden, sådan her.

Et skærmbillede af en åben HTML-sidemenu i iOS Safari

Den fulde kildekode til siden kan findes nederst i dette blogindlæg.

Forståelse af standardadfærd

Det første, jeg gjorde, var at prøve at forstå Safaris standardadfærd på iOS. Den mest bemærkelsesværdige observation var, at når du scrollede helt ned i menuen, udviste sidens indhold en 'gummibåndseffekt' - en hårdkodet funktion i Safari.

et animeret skærmbillede af den problematiske bounce-effekt i iOS Safari nederst på siden

Det samme skete, da jeg scrollede helt op til toppen af menuen.

et animeret skærmbillede af den problematiske gummibåndseffekt i iOS Safari øverst på siden

Men det første problem, jeg bemærkede, var, at hvis du fortsætter med at rulle helt op til toppen eller bunden, begynder Safari at vise renderingsfejl på både baggrundssiden og i menuen.

Jeg er ikke helt sikker på, hvorfor, men jeg formoder, at det har noget at gøre med gummibåndsfunktionen.

et animeret skærmbillede af et iOS Safari-problem, der giver glitches, nederst på siden

Forstå, hvad CSS-reglen "-webkit-overflow-scrolling" gør

Det næste, jeg gjorde, var at anvende CSS-reglen -webkit-overflow-scrolling på menuen, hvilket muliggør momentumbaseret rulning.

Som vist på billedet nedenfor fortsætter rulningen, selv efter at jeg har swipet med fingeren.

viser det momentumbaserede rulningsproblem på iOS Safari

Men det tilføjer også en gummibåndseffekt, når du ruller helt til toppen eller bunden, som vist nedenfor.

viser problemet med momentumbaseret rulning i iOS Safari med gummibåndseffekten

Brugeren skal vente, indtil gummibåndseffekten er færdig

Under mine tests bemærkede jeg også, at mens gummibåndseffekten er i gang, kan brugeren ikke flytte fokus til et andet element, før animationen er helt afsluttet.

I eksemplet nedenfor ruller jeg først på baggrundssiden og prøver derefter hurtigt at rulle i menuen, men ender med at fortsætte med at rulle på baggrundssiden i stedet.

viser at baggrundssiden er scrollet i stedet på iOS Safari

Men hvis jeg venter et øjeblik, indtil effekten er færdig, kan jeg derefter begynde at rulle gennem menuen.

viser ventetiden, indtil gummibåndseffekten er færdig i iOS Safari

Sådan forhindrer du, at baggrundssiden ruller

Under mine tests bemærkede jeg også, at mens gummibåndseffekten er i gang, kan brugeren ikke flytte fokus til et andet element, før animationen er helt afsluttet.

Baseret på dette svar fra Stack Overflow, kan du sikre, at elementer med disable-scrolling ikke udfører deres standard rulning, når touchmove-begivenheden udløses.

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(); } };

Og anvend derefter klassen disable-scrolling på diven til siden:

<div class="page disable-scrolling">

Denne løsning fungerer sådan set, men mere omfattende tests viser, at baggrundssiden stadig kan rulle nogle gange, når du når helt øverst eller helt nederst i menuen.

viser at baggrunden stadig bliver rullet

Sådan forhindrer du overscroll til baggrundssiden

Ved at anvende denne løsning bliver det muligt at forhindre 'overscroll'. Det betyder, at når et element er scrollet helt op eller helt ned, fortsætter rulleningen ikke videre til selve siden.

Som et resultat forhindres kroppen i at scrolle, hvilket også forhindrer gummibandseffekten i at opstå.

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"));

Hvad denne JavaScript-kode gør, er at forhindre, at elementet nogensinde når helt op til toppen eller helt ned til bunden ved at holde det kun 1 pixel væk.

Hvis rullepositionen aldrig når den absolutte top eller bund, kan der ikke opstå overscroll.

en demo, der viser, hvordan man forhindrer overscroll ved aldrig at nå helt til toppen eller helt til bunden

Sådan forhindrer du overscroll til baggrundssiden

Hvis du vil fjerne rubber-band-effekten fra menuen – enten af æstetiske årsager eller fordi, som i mit tilfælde, den medførte yderligere rendereringsfejl – fjern blot CSS-reglen -webkit-overflow-scrolling.

Men som du kan se nedenfor mister du også den glatte rulningseffekten.

Fuld demo, der viser, hvordan man forhindrer rubberbanding i iOS Safari.

Hele sidens kildekode

Her er hele kildekoden til siden.

<!-- 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>

Skrevet af Special Agent Squeaky. Først udgivet 2015-06-10. Sidst opdateret 2015-06-10.

📺 Se Squeaky's seneste video!

Sådan tilføjer du enkle undertekster i realtid til din livestream