ituy
ituy

Reputation: 241

Smooth animations

My goal: Achieve a smooth animation of sidemenu as this one of google (use button at top left corner on mobile version). (Animation smoothness i measure with a non high-end phone.)

I decided to test the absolutely most simple animation possible, and so created a draft at jsbin. Since then (several days) am really puzzled from the results - the ultimately most simple animation performs drastically worse than google's. (Ive tested mine on a dedicated url, so jsbin is not messing anything.)

Additionally there is the yandex translator with a similar menu (button is at top right). For sure there are other such good animations on the internet, but how do they play smoother than the most minimal setup?

I would set a bounty on this question as it is really important for me, but ... not enough reputation.


And second additionally - when testing my animations with 24 children in the animatables, results have no difference. I always thought that children count is important to be kept low.

[Ignore the following, stackoverflow forces me to paste it]

<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Sideanimations 0 children">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Sideanimations</title>
</head>
<body>
    <div class='buttonsholder'>
        <button onclick='ff1()'>by size</button>
        <button onclick='ff2()'>by position</button>
        <button onclick='ff3()'>both + rounded</button>
    </div>

  <div id='fikmic1'></div>
  <div id='fikmic2'></div>
  <div id='fikmic3'></div>


  <style>
  body{
        width:100vw;
        height:100vh;
        overflow:hidden;
    }
    .buttonsholder{
     position:absolute;
      bottom:50vh;
      right:0px;
      width:0px;
    }
    button{
        display:block;
        float:right;
      text-align:right;
      padding:0px 1vw;
      margin:.5vw 1vw;
    }

    #fikmic1{
        display:none;
        position:absolute;
      top:0vh;
      left:0vw;
        width:0vw;
        height:100vh;
        background-color:#777;
        transition:.7s;
    }
    #fikmic2{
        display:none;
        position:absolute;
      top:0vh;
      left:-80vw;
        width:80vw;
        height:100vh;
        background-color:#333;
        transition:.7s;
    }
    #fikmic3{
        display:none;
        position:absolute;
      top:50vh;
      left:0vw;
        width:0vw;
        height:0vh;
        background-color:#aaa;
      border-radius:100%;
        transition:.7s;
    }
  </style>

  <script>
      function ff1(){
        var c = document.getElementById('fikmic1');

        if(c.getAttribute('gefikt') === null){
          c.setAttribute('gefikt', '');
          c.style.display = 'block';
          setTimeout(function(){
            c.style.width = '80vw';
          }, 50);
        }
        else{
            c.removeAttribute('gefikt');
            c.style.width = '0vw';
          setTimeout(function(){
            c.style.display = 'none';
          }, 700);
        }
    }
    function ff2(){
        var c = document.getElementById('fikmic2');

        if(c.getAttribute('gefikt') === null){
          c.setAttribute('gefikt', '');
          c.style.display = 'block';
          setTimeout(function(){
            c.style.left = '0vw';
          }, 50);
        }
        else{
          c.removeAttribute('gefikt');
            c.style.left = '-80vw';
          setTimeout(function(){
            c.style.display = 'none';
          }, 700);
        }
    }
    function ff3(){
        var c = document.getElementById('fikmic3');

        if(c.getAttribute('gefikt') === null){
          c.setAttribute('gefikt', '');
          c.style.display = 'block';
          setTimeout(function(){
            c.style.top = (((window.innerHeight/100) * 50) - ((window.innerWidth/100) * 80)) + 'px';
            c.style.left = '-80vw';
            c.style.width = '160vw';
            c.style.height = '160vw';
          }, 50);
        }
        else{
          c.removeAttribute('gefikt');
            c.style.top = ((window.innerHeight/100) * 50) + 'px';
            c.style.left = '0vw';
            c.style.width = '0vw';
            c.style.height = '0vw';
          setTimeout(function(){
            c.style.display = 'none';
          }, 700);
        }
    }
  </script>


</body>
</html>

Upvotes: 2

Views: 311

Answers (1)

mfluehr
mfluehr

Reputation: 3217

Animating a CSS transform will be much more efficient than animating left, width, etc. "Modern browsers can animate four things really cheaply: position, scale, rotation and opacity."

When animating your first side menu, set the transform-origin property to left, so that the animation is centered on the left side of the menu. (The default origin is center, which isn't what you want in this case.)

I made a revised version of your JS Bin, and also posted it as a snippet below.

function ff1(){
  var c = document.getElementById('fikmic1');

  if(c.getAttribute('gefikt') === null){
    c.setAttribute('gefikt', '');
    c.style.display = 'block';
    setTimeout(function(){
      c.style.transform = 'scaleX(1)';
    }, 50);
  }
  else{
    c.removeAttribute('gefikt');
    c.style.transform = 'scaleX(0)';
    setTimeout(function(){
      c.style.display = 'none';
    }, 700);
  }
}

function ff2(){
  var c = document.getElementById('fikmic2');

  if(c.getAttribute('gefikt') === null){
    c.setAttribute('gefikt', '');
    c.style.display = 'block';
    setTimeout(function(){
      c.style.transform = 'translateX(0vw)';
    }, 50);
  }
  else{
    c.removeAttribute('gefikt');
    c.style.transform = 'translateX(-80vw)';
    setTimeout(function(){
      c.style.display = 'none';
    }, 700);
  }
}

function ff3(){
  var c = document.getElementById('fikmic3');

  if(c.getAttribute('gefikt') === null){
    c.setAttribute('gefikt', '');
    c.style.display = 'block';
    setTimeout(function(){
      c.style.transform = 'scale(1)';
    }, 50);
  }
  else{
    c.removeAttribute('gefikt');
    c.style.transform = 'scale(0)';
    setTimeout(function(){
      c.style.display = 'none';
    }, 700);
  }
}
body{
  width:100vw;
  height:100vh;
  overflow:hidden;
}
.buttonsholder{
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  justify-content:center;
  height:100%;
}
button{
  width:4rem;
  text-align:right;
  padding:0 .2rem;
  margin:.4rem .8rem;
}

#fikmic1{
  display:none;
  position:absolute;
  top:0vh;
  left:0vw;
  width:80vw;
  height:100vh;
  transform:scaleX(0);
  transform-origin:left;
  background-color:#777;
  transition:.7s;
}
#fikmic2{
  display:none;
  position:absolute;
  top:0vh;
  left:0vw;
  width:80vw;
  height:100vh;
  transform:translateX(-80vw);
  background-color:#333;
  transition:.7s;
}
#fikmic3{
  display:none;
  position:absolute;
  top:calc(50vh - 80vw);
  left:-80vw;
  width:160vw;
  height:160vw;
  transform:scale(0);
  background-color:#aaa;
  border-radius:100%;
  transition:.7s;
}
<!DOCTYPE html>
<html>
  <head>
    <meta name="description" content="Sideanimations by transform">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Sideanimations</title>
  </head>
  
  <body>
    <div class='buttonsholder'>
      <button onclick='ff1()'>by size</button>
      <button onclick='ff2()'>by position</button>
      <button onclick='ff3()'>both + rounded</button>
    </div>

    <div id='fikmic1'></div>
    <div id='fikmic2'></div>
    <div id='fikmic3'></div>
  </body>
</html>

Upvotes: 1

Related Questions