【问题标题】:CSS Transition item in and out of flexbox smooth animationCSS 过渡项目进出 flexbox 平滑动画
【发布时间】:2019-04-07 04:20:07
【问题描述】:

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

1:当处于“主页”状态时,网站徽标/图标较大且居中,位于其余导航/页面链接上方。

2:在除主页之外的任何其他页面上时,徽标/图标会更小,并与其他元素成比例地位于水平弹性框中。

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

如下所示,我已经实现了这一点,但是当页面全尺寸时,过渡是紧张的。我是 CSS 和 Angular 的新手,所以请提前原谅我的无知。

我的问题:

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

最终产品都将具有相似的背景颜色,但我在此插图中选择了明亮的颜色来显示 div 在背景中所做的事情。

注意:我尝试过使用“will-change”没有实际效果,而且我知道我可以在不使用 angular 的情况下做到这一点,但是除了这个简单的动画之外,还有一些功能将在以后使用 angular。

这也是一个小提琴: 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

【问题讨论】:

    标签: html css angularjs


    【解决方案1】:

    动画是“抖动”的,因为您一次为太多属性设置了动画,而且它们影响的不仅仅是 Paint 和 Composite 层。

    如果您觉得上述说法含糊不清,请参考以下两篇文章:

    对于这种类型的动画,普遍接受的解决方案是在 DOM 中为两种动画状态中的每一种设置一个元素。它们都应该被定位(除static 之外的任何position 值都可以)。您将使用transform 将起始状态元素设置为朝向目标状态元素的位置和大小的动画。通过在每个上获取.getBoundingClientRect(),您可以确定进行准确转换所需的转换)。

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

    一旦动画结束,您切换两个元素的 visibility 并从您刚刚制作动画的元素中删除 transforms(现在隐藏 - 您想设置 animation-duration:0s; 进行此更改),以重置渲染投影回到它在 DOM 中的正常位置。

    【讨论】:

    • 谢谢安德烈!我想我理解你为帮助我在两个状态之间平滑地为图标设置动画的方法,但我正在寻找的其他行为有(1:flexbox 中的其他项目,2:包含的大小区域3:容器下方的内容)全部响应动画。我很喜欢固执地尝试完成这项工作,但我是否对浏览器要求太多?我应该退缩并简化行为吗?或者您是否有任何其他优化我可能会专注于尝试解决这个问题?我还有很多东西要学,也谢谢你的资源。
    • @Will,使用transitionopacity 完成的动画非常“轻”,因为它们都不需要重新计算任何其他元素,除了动画元素。而触发布局更改的方法意味着动画后的每个元素都会在每一帧上重新计算。看起来可能不是这样,但计算上的差异是巨大的。只要您坚持第一种方法,一次可以制作动画的元素数量没有限制。
    猜你喜欢
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 2012-11-30
    • 2016-10-07
    相关资源
    最近更新 更多