FlexBox平滑动画的进出CSS过渡项目 [英] CSS Transition item in and out of flexbox smooth animation

查看:77
本文介绍了FlexBox平滑动画的进出CSS过渡项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为网站构建基本导航,而我想要的图形/动画功能是这样的:

I'm building basic navigation for a website, and the graphical/animated functionality that I would like is this:

1:处于"HOME"状态时,站点徽标/图标较大且居中,并位于其余导航/页面链接上方.

1: When in the 'HOME' state, the site logo/icon is large and centered and above the rest of the navigation/page links.

2:在首页以外的任何其他页面上,徽标/图标较小,并且与其他元素成比例地位于水平flexbox中.

2: When on any other page than home, the logo/icon is smaller, and sits proportionally in a horizontal flexbox with the other elements.

3:这两个状态之间有一个平滑的过渡.

3: There is a smooth transition between these two states.

我已经实现了这一点,如您在下面看到的那样,但是当页面已满时,过渡会令人不安.我是CSS和Angular的新手,所以请原谅我的无知.

I've implemented this already as you can see below, but the transition is jittery when page is full sized. I am new to both CSS and Angular, so forgive my ignorance in advance.

我的问题:

是否有比我这里提供的更好的方法来实现Flexbox动画的进/出,和/或是否缺少CSS动画优化来进一步平滑过渡?

Is there a better way to implement a into/out-of flexbox animation than i've provided here, and/or is there a CSS animation optimization that I am missing to smooth this transition further?

最终产品都将具有相似的背景色,但是在此图中,我选择了鲜艳的颜色来显示div在背景中的作用.

The end product will all have a similar background color, but I have chosen bright colors in this illustration to show what the divs are doing in the background.

注意:我尝试使用'will-change'不会产生任何实际效果,并且我知道我可以在不使用角度的情况下做到这一点,但是除了这个简单的动画之外,还有一些功能可以在将来使用角度.

Note: I've tried using 'will-change' to no real effect, and I'm aware that I can do this without using angular, but there are features beyond this simple animation that will utilize angular down the road.

这里也是一个小提琴: https://jsfiddle.net/willcthomson/f6wk4Lpq/

Here is a fiddle for it too: https://jsfiddle.net/willcthomson/f6wk4Lpq/

/* angular */ 
function mainCtrl($scope) { 

  		$scope.ng_div_home = 'div_home_scale_up';
      $scope.ng_div_logo = 'div_logo_scale_up';
      $scope.ng_div_logo_upper_container = 'div_logo_upper_container_scale_up';
      $scope.ng_logo = '';
      $scope.ng_ISHOME = true;

  		$scope.f_scale = function()
  				{
            if(!$scope.ng_ISHOME)
              {
              $scope.ng_div_home = "div_home_scale_down";
              $scope.ng_div_logo = "div_logo_scale_down";
              $scope.ng_div_logo_upper_container = 'div_logo_upper_container_scale_down';
              }
            else
              {
              $scope.ng_div_home = "div_home_scale_up";
              $scope.ng_div_logo = "div_logo_scale_up";
              $scope.ng_div_logo_upper_container = 'div_logo_upper_container_scale_up';
              }
            console.log("ishome is:"+$scope.ng_ISHOME);
  				};


}

/* css */
html{
  position: relative;
  min-height: 100%;
  background-color: #222222;
  }

body{
  background-color: #00000000;
  }


/*a container that sits on top of the nav bar and grows vertically to make room fo the expanding logo-icon*/
.div_logo_upper_container 
  {
    /* background-color: #111111; */
    background-color: magenta;
    width: 80%;
    margin: auto;
    transition: height .5s linear;
    margin-top: 5vw;
  }

/*a flex container to hold nav elements*/
.nav_container 
  {
    /* background-color: #111111; */
    background-color: yellow;
    width: 80%;
    
    margin: auto;
    display: flex;    
    
    align-items: stretch;
    align-items: flex-end;
 
  }
  

/*a div that scales forcing the other flex elements respond */
.div_home
    {
      background-color: #00000000;
      background-color: cyan;
      margin: auto;
      transition: .5s linear;
      will-change: transform, width, flex,;
    }

/*a div that holds the logo, and does the actual scaling and movement*/
.div_logo    
    {
      padding: 3px;
      margin: 3px;
      margin-left: 2vw;
      transition:  .5s linear;
      will-change: width;
    }

.img_logo   
    {
    max-width:100%;
    max-height: 100%;
    min-width: 8%;
    min-height: 8%;
    will-change:width;
    will-change:height;
    }

/*expands the home container amongst the other flex elements to make room for incoming logo*/
.div_home_scale_down
  {
    width: 10vw;
    flex: .5 1 40px;
  }    

/*shrinks the home container to allow flex elements to expand into the created gap*/
.div_home_scale_up
  {
    width: 3px;
    transform: translate(25vw,-10vh);
    align-self: center;
  }    

/*expands the logo container*/
.div_logo_scale_up
  {
    width: 30vw;
    margin-top: 5vh;
  }

/*shrinks the logo container*/
.div_logo_scale_down
  {
    margin: 1vh;
    width: 10vw;  
    position: static;

  }

/*expands the area above the nav container to contain the larger icon*/
.div_logo_upper_container_scale_up
  {
    height: 10vh;
  }  

/*shrinks the upper container as the icon files in with other elements  */
.div_logo_upper_container_scale_down
  {
    height: 1px;
  }  

.nav_items
    {
    flex: 1 1 10px;
    margin-bottom: 2vh;

    font-family: verdana;
    font-size: 30px;
    color:grey;
    text-align: center;
    margin: 3px;
    transition: font-size, color, transform, .5s linear;
    }  

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!--html-->
<div ng-app>
<div ng-controller="mainCtrl">

<div class="div_logo_upper_container" ng_class="ng_div_logo_upper_container"></div>
<div class="nav_container">
    <div class = "div_home" ng-class="ng_div_home">
      <div class = "div_logo" ng-class="ng_div_logo" ng-click="ng_ISHOME=true;f_scale();">
        <img  class = "img_logo" src="https://avatars1.githubusercontent.com/u/579414?s=200&v=4" > 
      </div>
    </div>
  	<div  class = "nav_items">  	
  		<p ng-click="ng_ISHOME=false;f_scale();">Two</p>
  	</div>
  	<div class = "nav_items">
  		<p ng-click="ng_ISHOME=false;f_scale();">Three</p>
  	</div>
  	<div class = "nav_items">
  		<p ng-click="ng_ISHOME=false;f_scale();">Four</p>
  	</div>
    
  </div> <!-- end nav_container -->
  </div> <!-- end ctrl -->
  </div> <!-- end app -->

asdf

推荐答案

动画是抖动的",因为您一次要设置过多的属性,并且它们影响的范围比"Paint"和"Composite"层更大.

The animation is "jittery" because you are animating too many properties at once and they affect more than Paint and Composite layers.

如果您发现上述声明含糊不清,请参阅这两篇文章:

If you find the above statement vague, please refer to these two articles:

这种动画的普遍接受的解决方案是在DOM中为两个动画状态的每一个都包含一个元素.它们都应该定位(除了 static 以外的任何 position 值都可以).您将使用 transform 将起始状态元素动画化为目标状态元素的位置和大小.通过分别获取 .getBoundingClientRect(),您可以可以确定进行精确过渡所需的所需变换.

The generally accepted solution for this type of animations is to have one element in DOM for each of the two animation states. They should both be positioned (any position value other than static will do). You'll use transform to animate the starting state element towards the position and size of the target state element. By getting .getBoundingClientRect() on each, you can determine the required transforms needed to make the exact transition).

到目前为止,此方法的最大优点是,要设置动画的元素在文档流中保持相同的位置,并且由于不进行大小调整或移动,它不会触发后续DOM元素或父元素的重排.仅其渲染的投影被移动.

By far, the biggest advantage of this method is that the element being animated remains at the same position in document flow and, by not being resized or moved, it doesn't trigger reflow on subsequent DOM elements or parents. Only its rendered projection is moved.

动画结束后,您可以切换两个元素的 visibility 并从刚制作动画的元素中删除 transform (现在已隐藏-您要设置 animation-duration:0s; 进行此更改),以便将渲染的投影重置回DOM中的正常位置.

Once the animation ends, you toggle both elements's visibility and remove the transforms from the one you just animated (now hidden - you want to set animation-duration:0s; for this change), in order to reset the rendered projection back to its normal place in DOM.

这篇关于FlexBox平滑动画的进出CSS过渡项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆