javascript - CSS-overgangshendelser ekstremt langsomme på IOS


Jeg utvikler en enkelt-side Javascript-applikasjon som kjører på skrivebordsnettlesere og også på mobile enheter via Cordova/Phonegap.

Jeg har en skyve-meny som er implementert ved hjelp av CSS-overganger. Jeg har lagt merke til at den fungerer bra på stasjonære nettlesere og Android. Imidlertid er det alvorlige ytelsesproblemer på iOS. Overgangen ser ikke ut til å starte i tide, men når den først starter, ser gjengivelsen og varigheten bra ut. Tiden mellom å starte overgangen og transitionend-hendelsen er mye lengre på iOS enn på andre plattformer. For eksempel er varigheten av overgangen 300 ms, men jeg får ikke transitionend-hendelsen før etter 1500 ms. På alle andre plattformer får jeg transitionend-hendelsen innen 325-350 ms.

Transitionend-hendelse:

  • Forventet: 350 ms
  • Faktisk: 1500 ms

Plattformer :

  • Cordova 6.3.1
  • Xcode 8.1 GM Seed
  • IOS 10.1

Her er CSS-en for menydelen. For å skyve ut menyen, legger jeg til klassen 'open'. For å lukke menyen, fjerner jeg klassen 'open'. Jeg har prøvd å bruke overgang på 'left'-egenskapen og 'transform'-egenskapen, men resultatene er identiske.

/* Nav Menu */

#navmenu {
    position: absolute;
    top: 0;
    width: 90%;
    max-width: 400px;
    z-index: 20;
    height: auto;
    background-color: white;
    /*
    -webkit-transform: translate3d(-100%,0,0);
       -moz-transform: translate3d(-100%,0,0);
        -ms-transform: translate3d(-100%,0,0);
            transform: translate3d(-100%,0,0);
    -webkit-transition: -webkit-transform 300ms ease;
       -moz-transition:    -moz-transform 300ms ease;
        -ms-transition:     -ms-transform 300ms ease;
         -o-transition:      -o-transform 300ms ease;
            transition:         transform 300ms ease;
    */
    left: -100%;
    -webkit-transition: left 300ms ease;
       -moz-transition: left 300ms ease;
        -ms-transition: left 300ms ease;
         -o-transition: left 300ms ease;
            transition: left 300ms ease;
}

#navmenu.open {
    /*
    -webkit-transform: translate3d(0,0,0);
       -moz-transform: translate3d(0,0,0);
        -ms-transform: translate3d(0,0,0);
            transform: translate3d(0,0,0);
    -webkit-transition: -webkit-transform 300ms ease;
       -moz-transition:    -moz-transform 300ms ease;
        -ms-transition:     -ms-transform 300ms ease;
         -o-transition:      -o-transform 300ms ease;
            transition:         transform 300ms ease;
    */
    left: 0;
    -webkit-transition: left 300ms ease;
       -moz-transition: left 300ms ease;
        -ms-transition: left 300ms ease;
         -o-transition: left 300ms ease;
            transition: left 300ms ease;
}

Spørsmål: Hva kan være årsaken til forsinkelsen i å starte overgangen, bare på IOS-plattformer? Finnes det noen kjente løsninger for å omgå problemet eller få ting til å gå raskere? Jeg har andre overganger i appen som tar over 5 sekunder å starte, noe som gjør appen ubrukelig. Jeg håper at meny-løsningen vil gjelde for hele appen. Takk for all hjelp eller ideer du kan gi.

Her er den instrumenterte Javascript-koden jeg bruker for å åpne/lukke menyen...

utilities.addEventListeners(navMenuButtonDiv, function () {
    var start = Date.now();
    var menuDiv = navMenu.getDiv();
    if (menuDiv.classList.contains('open')) {
        menuDiv.classList.remove('open');
    } else {
        menuDiv.classList.add('open');
    }
    var handler = function (event) {
        console.log('Transition: ' + (Date.now() - start));
        menuDiv.removeEventListener('webkitTransitionEnd', handler, true);
    };
    menuDiv.addEventListener('webkitTransitionEnd', handler, true);
 };

Svar #1

Når du flytter elementer rundt på skjermen, ønsker du å maksimere ytelsen. I stedet for å animere left-egenskapen, er det bedre å bruke transformasjon. Ved å bruke transformasjon vil enheten bruke GPU-en sin til å gjengi endringen på skjermen, på et lag over DOM. Dette vil resultere i en jevnere og mer ytelseseffektiv overgang.

Ta en titt på dette eksemplet. I tillegg til å bruke en transform i stedet for å endre left-egenskapen, legg merke til at jeg fjernet litt overflødighet. Du trenger ikke å erklære overgangen på nytt i den aktive tilstanden.

var open = document.getElementById("open"),
    close = document.getElementById("close"),
    nav = document.getElementById("navmenu");

open.addEventListener("click", function() {
  nav.classList.add("open");
}); 

close.addEventListener("click", function() {
  nav.classList.remove("open");
});
#navmenu {
  position: absolute;
  top: 0;
  left: 0;
  width: 90%;
  max-width: 400px;
  z-index: 20;
  height: auto;
  background-color: white;
  transform: translate3d(-100%, 0, 0);
  -webkit-transition: transform 300ms ease-in-out;
     -moz-transition: transform 300ms ease-in-out;
      -ms-transition: transform 300ms ease-in-out;
       -o-transition: transform 300ms ease-in-out;
          transition: transform 300ms ease-in-out;
}

#navmenu.open {
  transform: translate3d(0, 0, 0);
}

button {
  margin-top: 100px;
}
<div id="navmenu">stuff in here</div>
<button id="open">Open Menu</button>
<button id="close">Close Menu</button>