最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - CSS transition events extremely slow on IOS - Stack Overflow

programmeradmin1浏览0评论

I am developing a single-page Javascript application that runs on desktop browsers and also on mobile devices via Cordova/Phonegap.

I have a slide-out menu that is implemented using CSS transitions. I noticed that it works well on desktop browsers and android. However, on IOS there are serious performance issues. The transition does not appear to start on time, but once it starts the rendering and duration looks fine. The time between starting the transition and the transitionend event is way higher on IOS than other platforms. For example, the duration of the transition is 300ms but I'm not getting the transitionend event for 1500ms. On all other platforms, I get the transitionend event in 325-350ms.

Transitionend Event:

  • Expected: 350ms
  • Actual: 1500ms

Platforms:

  • Cordova 6.3.1
  • Xcode 8.1 GM Seed
  • IOS 10.1

Here is the CSS for the menu div. To slide-out the menu, I add the 'open' class. To close the menu, I remove the 'open' class. I've tried transitioning on the 'left' property and 'transform' property, but the results are identical.

/* 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;
}

Question: What might be causing the delay in starting the transition, only on IOS platforms? Are there any known solutions to circumvent the problem or speed things up? I have other transitions in the app that take over 5s to start, making the app unusable. I'm hoping the menu solution will apply throughout the app. Thanks for any help or ideas you can provide.

Here is the instrumented Javascript code that I use to open/close the menu...

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

I am developing a single-page Javascript application that runs on desktop browsers and also on mobile devices via Cordova/Phonegap.

I have a slide-out menu that is implemented using CSS transitions. I noticed that it works well on desktop browsers and android. However, on IOS there are serious performance issues. The transition does not appear to start on time, but once it starts the rendering and duration looks fine. The time between starting the transition and the transitionend event is way higher on IOS than other platforms. For example, the duration of the transition is 300ms but I'm not getting the transitionend event for 1500ms. On all other platforms, I get the transitionend event in 325-350ms.

Transitionend Event:

  • Expected: 350ms
  • Actual: 1500ms

Platforms:

  • Cordova 6.3.1
  • Xcode 8.1 GM Seed
  • IOS 10.1

Here is the CSS for the menu div. To slide-out the menu, I add the 'open' class. To close the menu, I remove the 'open' class. I've tried transitioning on the 'left' property and 'transform' property, but the results are identical.

/* 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;
}

Question: What might be causing the delay in starting the transition, only on IOS platforms? Are there any known solutions to circumvent the problem or speed things up? I have other transitions in the app that take over 5s to start, making the app unusable. I'm hoping the menu solution will apply throughout the app. Thanks for any help or ideas you can provide.

Here is the instrumented Javascript code that I use to open/close the menu...

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);
 };
Share Improve this question edited Oct 28, 2016 at 3:29 jmelvin asked Oct 28, 2016 at 3:12 jmelvinjmelvin 6571 gold badge10 silver badges17 bronze badges 1
  • UPDATE: The latest update to IOS (10.1.1) appears to have exacerbated the problem quite considerably. Even after porting top/left to transitioning on transforms, it is still a problem. Any transition on iPhone5 starts very late, sometimes well more than 5 seconds after button click/touch. Performance is somewhat better on iPhone6, leading me to believe it's a memory issue and perhaps a bit of planned obsolescence to get people off old iPhones. Try the app on an older iPhone for a demo at sizzlescene.. – jmelvin Commented Nov 23, 2016 at 15:18
Add a ment  | 

1 Answer 1

Reset to default 6

When moving elements around the screen, you want to maximize performance. Instead of transitioning the left property, you're better off using translation. Using translation, the device will use its GPU to render the onscreen change, on a layer above the DOM. This will result in a smoother, more performant transition.

Have a look at this example. Besides using a transform instead of changing the left property, notice that I removed a bit of redundancy. You don't need to redeclare the transition on the active state.

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>

发布评论

评论列表(0)

  1. 暂无评论