locked
Optimize WinJS.Animation.executeTransition of 4 properties RRS feed

  • Question

  • I wonder if that sequence can be optimized a bit:

    WinJS.UI.executeTransition(splashImage, [
            {
              property: "left",
              delay: 0,
              duration: 400,
              timing: "ease-out",
              to: "120px"
            }, {
              property: "top",
              delay: 0,
              duration: 400,
              timing: "ease-out",
              to: "43px"
            }, {
              property: "width",
              delay: 0,
              duration: 400,
              timing: "ease-out",
              to: "135px"
            }, {
              property: "height",
              delay: 0,
              duration: 400,
              timing: "ease-out",
              to: "61px"
            }
          ]);

    When the rest of the page is playing a page in transition also, this animation is also a bit sluggish. I was under the impression that its pure CSS and performed on the GPU?

    Tuesday, March 12, 2013 1:52 PM

Answers

  • Where animations are concerned, not all CSS properties are created equal. :)

    Only those animations that affect opacity and transform properties will run in the GPU (an "independent animation"), otherwise they run on the UI thread (a "dependent animation"). As you're animating left, top, width, and height, you're getting a dependent/UI thread animation.

    You'll want, then, to rewrite your animation in terms of CSS transform (see W3C spec). Left and top can be covered with a translate transform, width and height with a scale transform. When writing out an executeTransition, you'll use property: mstransform and to: "translate(...) scale(...)". Take a look in the WinJS ui.js file and search for executeTransition, and you'll see examples. As a simple one, here's the description for the pointerDown animation:

    {
        property: mstransform,
        delay: 0,
        duration: 167,
        timing: "cubic-bezier(0.1, 0.9, 0.2, 1)",
        to: "scale(0.975, 0.975)"
    }

    Your code suggests you're moving your splash screen image on an extended splash screen. So you should be able to get the exact size/position of the splash screen image that you'll need to calculate the exact translate offset and scaling. A little math, but that should make the animation run smoothly. The Independent animations sample might be of help here too.

    Kraig

    Author, Programming Windows 8 Apps with HTML, CSS, and JavaScript, a free ebook from Microsoft Press


    Tuesday, March 12, 2013 4:02 PM

All replies

  • Where animations are concerned, not all CSS properties are created equal. :)

    Only those animations that affect opacity and transform properties will run in the GPU (an "independent animation"), otherwise they run on the UI thread (a "dependent animation"). As you're animating left, top, width, and height, you're getting a dependent/UI thread animation.

    You'll want, then, to rewrite your animation in terms of CSS transform (see W3C spec). Left and top can be covered with a translate transform, width and height with a scale transform. When writing out an executeTransition, you'll use property: mstransform and to: "translate(...) scale(...)". Take a look in the WinJS ui.js file and search for executeTransition, and you'll see examples. As a simple one, here's the description for the pointerDown animation:

    {
        property: mstransform,
        delay: 0,
        duration: 167,
        timing: "cubic-bezier(0.1, 0.9, 0.2, 1)",
        to: "scale(0.975, 0.975)"
    }

    Your code suggests you're moving your splash screen image on an extended splash screen. So you should be able to get the exact size/position of the splash screen image that you'll need to calculate the exact translate offset and scaling. A little math, but that should make the animation run smoothly. The Independent animations sample might be of help here too.

    Kraig

    Author, Programming Windows 8 Apps with HTML, CSS, and JavaScript, a free ebook from Microsoft Press


    Tuesday, March 12, 2013 4:02 PM
  • Great Kraig! It works now buttery smooth :) Thanks a lot! I even got the calculations for scaling and translate right. Had to change the transform offset to "0 0" though for it to work.
    • Edited by phil_ke Thursday, March 14, 2013 5:06 PM changed type from "not" to "now"
    Wednesday, March 13, 2013 10:14 AM
  • Excellent. Did you mean to write "now buttery smooth"? That's a typo I often make too, and it changes the meaning significantly. :)

    Also, would you be willing to post your code so we have the solution to your original question here in the thread?

    Thursday, March 14, 2013 4:26 PM
  • yeah Kraig, meant to write "now" :) Good catch.

    Here is my solution:

    hideSplash = function() {
        var extendedSplashScreen, pageLogo, scaleX, scaleY, transitionPromise;
        extendedSplashScreen = document.getElementById('extendedSplashScreen');
        if (!(splash && extendedSplashScreen)) {
          return;
        }
        pageLogo = document.querySelector("img.logo");
        if (pageLogo) {
          pageLogo.style.opacity = 0;
          scaleX = pageLogo.width / splashImage.width;
          scaleY = pageLogo.height / splashImage.height;
          transitionPromise = WinJS.UI.executeTransition(splashImage, [
            {
              property: "transform",
              delay: 0,
              duration: 400,
              timing: "ease-out",
              to: "translate(" + (pageLogo.offsetLeft - splashImage.offsetLeft) + "px, " + (pageLogo.offsetTop - splashImage.offsetTop) + "px) scale(" + scaleX + "," + scaleY + ")"
            }
          ]);
        } else {
          transitionPromise = WinJS.Promise.as();
        }
        transitionPromise.then(function() {
          pageLogo.style.opacity = 1;
          return splashImage.parentElement.removeChild(splashImage);
        });
        return WinJS.UI.Animation.fadeOut(extendedSplashScreen).then(function() {
          return extendedSplashScreen.parentElement.removeChild(extendedSplashScreen);
        });
      };
    
    splash = event.detail.splashScreen;
    splash.addEventListener('dismissed', function() {
      hideSplash();
    });

    and the html part of my default.html

    <body>
        <div id="extendedSplashScreen" class="extendedSplashScreen">     
          <progress id="extendedSplashProgress" class="win-medium win-ring"></progress>
          <div id="extendedSplashText" data-win-res="{innerText: 'application/status.startup'}"></div>
        </div><img id="extendedSplashImage" src="/images/backgrounds/logo.svg">
      

    and the css

    #extendedSplashImage {
      ;
      z-index: 1000;
      transform-origin: 0 0;
    }
    .extendedSplashScreen {
      z-index: 1000;
      background-color: #e8edf0;
      height: 100%;
      width: 100%;
      ;
      top: 0px;
      left: 0px;
      text-align: center;
    }
    .extendedSplashScreen #extendedSplashText {
      ;
      width: 100%;
      top: calc(100% - 140px);
      text-align: center;
      opacity: 0;
      animation: fadeIn 0.5s ease-in 2s forwards;
    }

    CRAZY EDITOR removes all  "" from all css statements. So where you see just a ";" think of ";"

    Might put this into a small library in the future for easier reuse so others can just drop the .js into their project and get this nice effect too.



    • Edited by phil_ke Thursday, March 14, 2013 5:15 PM
    Thursday, March 14, 2013 5:12 PM