Šis ieraksts publicēts 2015. gada jūnijā — dažas detaļas kopš tā laika var būt mainījušās. Centīšos atjaunot, kad būs iespēja!
- Mana testa lapa
- Izpratne par noklusēto uzvedību
- Izpratne par to, ko dara CSS noteikums "-webkit-overflow-scrolling"
- Lietotājam jāgaida, līdz rubber-band efekts beigsies.
- Kā apturēt fona lapas ritināšanu
- Kā novērst pārmērīgu ritināšanu uz fona lapu
- Kā novērst pārlieko ritināšanu uz fona lapu
- Visas lapas avota kods
Lai novērstu nesenu ritināšanas problēmu iOS Safari pārlūkprogrammā, man nācās izveidot savu vienkāršo testa lapu un pēc tam pielietot visu internetā atrasto informāciju un dažādas kombinācijas, lai mēģinātu problēmu atrisināt.
Zemāk ir īss pārskats par to, ko es šajā procesā esmu atklājis.
Mana testa lapa
Mana testa lapa bija diezgan vienkārša. Tā sastāvēja no fiktīviem datiem statiskā 'div' elementā, lai attēlotu lapu, kā arī no fiksēta 'div' elementa, kas pārklāja virs lapas esošo 'izvēlni' — tāpat kā šeit.
Šīs lapas pilnais avota kods ir atrodams šī bloga ieraksta apakšā.
Izpratne par noklusēto uzvedību
Pirmais, ko es izdarīju, bija mēģināt saprast Safari uzvedību iOS pēc noklusējuma. Pamanākais novērojums bija tas, ka, ritinot visu lapas garumu līdz pat apakšai, lapas saturs izrādījās ar "gumijas atsperes efektu" — tā bija Safari iebūvēta funkcija.
Tas pats notika, ritinot līdz izvēlnes augšējai daļai.
Tomēr pirmais, ko pamanīju, bija tas, ka, ja nepārtraukti ritināt uz augšējo vai apakšējo malu, Safari sāk rādīt renderēšanas kļūdas gan fona lapā, gan izvēlnē.
Es īsti nezinu, kāpēc, bet domāju, ka tas varētu būt saistīts ar gumijas lentes funkciju.
Izpratne par to, ko dara CSS noteikums "-webkit-overflow-scrolling"
Nākamā lieta, ko izdarīju, bija pielietot -webkit-overflow-scrolling CSS noteikumu izvēlnei, kas ļauj ritināšanai ar inerci.
Kā redzams zemāk esošajā attēlā, ritināšana turpinās pat pēc tam, kad es pavelku ar pirkstu.
Bet tas piešķir arī gumijas atsperes efektu, ritinot uz augšējo vai apakšējo malu, kā parādīts zemāk.
Lietotājam jāgaida, līdz rubber-band efekts beigsies.
Testēšanas laikā es arī pamanīju, ka kamēr gumijas lentes efekts notiek, lietotājs nevar pievērst uzmanību citam elementam, līdz animācija ir pilnībā pabeigta.
Zemāk redzamajā piemērā vispirms ritinu fonā esošo lapu, pēc tam ātri mēģinu ritināt izvēlni, taču beigās turpinu ritināt fonā esošo lapu.
Tomēr, ja uz mirkli pagaidīšu, kamēr efekts beigsies, tad varēšu sākt ritināt izvēlni.
Kā apturēt fona lapas ritināšanu
Testēšanas laikā es arī pamanīju, ka, kamēr notiek gumijveida efekts, lietotājs nevar pāriet uz citu elementu, līdz animācija ir pilnībā pabeigta.
Pamatojoties uz šo atbildi no Stack Overflow, jūs varat nodrošināt, ka elementi ar disable-scrolling neizpilda savas noklusētās ritināšanas darbības, kad tiek izraisīts touchmove notikums.
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();
}
};
Un tad pielietojiet disable-scrolling klasi lapas
<div class="page disable-scrolling">
Šis risinājums strādā vismaz daļēji, taču plašāki testi rāda, ka fona lapa dažkārt joprojām var ritināties, kad tiek sasniegta izvēlnes augšējā vai apakšējā mala.
Kā novērst pārmērīgu ritināšanu uz fona lapu
Pielietojot šo labojumu, ir iespējams novērst "overscrolling". Tas nozīmē, ka, ritinot elementu līdz tā augšējai vai apakšējai robežai, ritināšana nepāriet uz lapas saturu.
Tāpēc lapas ritināšana tiek liegta, un tas arī novērš gumijas atsitiena efektu.
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"));
Šis JavaScript koda gabals novērš to, ka elements jebkad sasniedz pašu augšējo vai apakšējo robežu, uzturot to 1 pikseļa attālumā.
Ja ritināšana nekad nesasniedz absolūto augšējo vai apakšējo malu, overscroll nav iespējams.
Kā novērst pārlieko ritināšanu uz fona lapu
Ja vēlaties noņemt gumijas joslas efektu no izvēlnes — gan estētisku apsvērumu dēļ, gan tāpēc, ka manā gadījumā tas izraisīja papildu renderēšanas problēmas — vienkārši noņemiet -webkit-overflow-scrolling CSS noteikumu.
Tomēr, kā zemāk redzams, jums arī pazūd gludās ritināšanas sajūta.
Visas lapas avota kods
Šeit ir šīs lapas pilnais avota kods.
<!-- 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>