【问题标题】:CSS Slide in and out animation overflow issueCSS滑入和滑出动画溢出问题
【发布时间】:2016-04-16 06:37:27
【问题描述】:

我正在尝试为屏幕外的图块列表设置动画,同时在屏幕上为新的图块列表设置动画。

我正在使用 Angular 的 ng-for 循环遍历一组可见项目,因此从技术上讲只有一个列表,但 Angular 的 ngAnimate 模块使被驱逐的项目保持活动状态,直到动画完成。

我的问题是,每当两个图块列表在动画中间同时出现在屏幕上时,一个就会溢出并最终落在另一个之下。

这是正在发生的事情:

这就是我想要它做的:

我尝试过使用 CSS 转换、绝对定位,但我似乎无法正确处理。

这里有一个可行的例子:http://jsfiddle.net/soethzfm/7/

(function() {
  var app = angular.module("animationApp", ["ngAnimate"]);

  app.controller('FrameController', ['$scope',
    function($scope) {

      $scope.message = 'Hello world';
      $scope.items = [];
      $scope.visibleItems = [];
      for (var i = 3; i < 9; i++) {
        $scope.items.push({
          name: 'Item ' + (i - 2),
          color: "#" + (i) + "0" + (i % 5) + "0" + (i % 4) + '0'
        });
      }


      $scope.firstThree = true;
      $scope.selectNextItems = function() {
        if ($scope.firstThree) {
          $scope.firstThree = false;
          $scope.visibleItems = [$scope.items[0], $scope.items[1], $scope.items[2]];
        } else {
          $scope.firstThree = true;
          $scope.visibleItems = [$scope.items[3], $scope.items[4], $scope.items[5]];
        }
      }
      $scope.selectNextItems();
    }
  ]);
})()
.item-container {
  width: 400px;
  border: 1px solid red;
  overflow: hidden;
}
.item {
  color: white;
  width: 100px;
  height: 150px;
  border: 5px solid #F3F5F6;
  display: inline-block;
  position: relative;
  cursor: pointer;
}
.item:hover {
  padding: 2px;
  border: 3px solid blue;
}
/* Animations */

.item.ng-move,
.item.ng-enter,
.item.ng-leave {
  -webkit-transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
  -moz-transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
  -ms-transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
  -o-transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
  transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
}
.item.ng-enter,
.item.ng-move {
  left: -100%;
}
.item.ng-enter.ng-enter-active,
.item.ng-move.ng-move-active {
  left: 0;
}
.item.ng-leave {
  right: 0;
}
.item.ng-leave.ng-leave-active {
  right: -100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.min.js"></script>
<div ng-app="animationApp">
  <div ng-controller="FrameController as vm">

    <button ng-click="selectNextItems()">Next Page</button>

    <div class="item-container">

      <div class="item" ng-repeat="item in visibleItems" ng-style="{'background-color': item.color}">
        {{item.name}}
      </div>
    </div>
  </div>
</div>

【问题讨论】:

    标签: html css angularjs css-animations ng-animate


    【解决方案1】:

    您面临的问题是因为内容被包裹在父容器中。父容器的宽度只有 400 像素,但每个框都是 100 像素 + 2 * 5 像素(用于边框)宽。所以只有 3 个盒子可以放在同一行,其余的必须绕到下一行。当您同时使所有 6 个元素可见时,可以非常清楚地看到这一点。正如您在下面的 sn-p 中看到的,最后 3 项环绕到下一行。

    注意:我对 AngularJS 一无所知,因此请原谅我试图让所有六个同时可见。

    (function() {
      var app = angular.module("animationApp", ["ngAnimate"]);
    
      app.controller('FrameController', ['$scope', function($scope) {
       
        $scope.message = 'Hello world';
        $scope.items = [];
        $scope.visibleItems = [];
        for (var i = 3; i < 9; i++) {
          $scope.items.push({
            name: 'Item ' + (i - 2),
            color: "#" + (i) + "0" + (i % 5) + "0" + (i % 4) + '0'
          });
        }
    
    
        $scope.firstThree = true;
        $scope.selectNextItems = function() {
          if ($scope.firstThree) {
            $scope.firstThree = false;
            $scope.visibleItems = [$scope.items[0], $scope.items[1], $scope.items[2], $scope.items[3], $scope.items[4], $scope.items[5]];
          } else {
            $scope.firstThree = true;
            $scope.visibleItems = [$scope.items[3], $scope.items[4], $scope.items[5]];
          }
        }
        $scope.selectNextItems();
      }]);
    })()
    .item-container {
      width: 400px;
      border: 1px solid red;
      overflow: hidden;
    }
    .item {
      color: white;
      width: 100px;
      height: 150px;
      border: 5px solid #F3F5F6;
      display: inline-block;
      position: relative;
      cursor: pointer;
    }
    .item:hover {
      padding: 2px;
      border: 3px solid blue;
    }
    /* Animations */
    
    .item.ng-move,
    .item.ng-enter,
    .item.ng-leave {
      transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    }
    .item.ng-enter,
    .item.ng-move {
      left: -80%;
    }
    .item.ng-enter.ng-enter-active,
    .item.ng-move.ng-move-active {
      left: 0%;
    }
    .item.ng-leave {
      right: 0%;
    }
    .item.ng-leave.ng-leave-active {
      right: -100%;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.min.js"></script>
    <div ng-app="animationApp">
      <div ng-controller="FrameController as vm">
    
        <button ng-click="selectNextItems()">Next Page</button>
    
        <div class="item-container">
    
          <div class="item" ng-repeat="item in visibleItems" ng-style="{'background-color': item.color}">
            {{item.name}}
          </div>
        </div>
      </div>
    </div>

    可以通过向父容器添加white-space: nowrap 设置轻松解决此问题。通过这样做,我们可以让所有六个元素排列在同一行上,这样动画期间看到的不匹配就会消失。

    (function() {
      var app = angular.module("animationApp", ["ngAnimate"]);
    
      app.controller('FrameController', ['$scope', function($scope) {
       
        $scope.message = 'Hello world';
        $scope.items = [];
        $scope.visibleItems = [];
        for (var i = 3; i < 9; i++) {
          $scope.items.push({
            name: 'Item ' + (i - 2),
            color: "#" + (i) + "0" + (i % 5) + "0" + (i % 4) + '0'
          });
        }
    
    
        $scope.firstThree = true;
        $scope.selectNextItems = function() {
          if ($scope.firstThree) {
            $scope.firstThree = false;
            $scope.visibleItems = [$scope.items[0], $scope.items[1], $scope.items[2]];
          } else {
            $scope.firstThree = true;
            $scope.visibleItems = [$scope.items[3], $scope.items[4], $scope.items[5]];
          }
        }
        $scope.selectNextItems();
      }]);
    })()
    .item-container {
      width: 400px;
      border: 1px solid red;
      overflow: hidden;
      white-space: nowrap;
    }
    .item {
      color: white;
      width: 100px;
      height: 150px;
      border: 5px solid #F3F5F6;
      display: inline-block;
      position: relative;
      cursor: pointer;
    }
    .item:hover {
      padding: 2px;
      border: 3px solid blue;
    }
    /* Animations */
    
    .item.ng-move,
    .item.ng-enter,
    .item.ng-leave {
      transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    }
    .item.ng-enter,
    .item.ng-move {
      left: -80%;
    }
    .item.ng-enter.ng-enter-active,
    .item.ng-move.ng-move-active {
      left: 0%;
    }
    .item.ng-leave {
      right: 0%;
    }
    .item.ng-leave.ng-leave-active {
      right: -100%;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.min.js"></script>
    <div ng-app="animationApp">
      <div ng-controller="FrameController as vm">
    
        <button ng-click="selectNextItems()">Next Page</button>
    
        <div class="item-container">
    
          <div class="item" ng-repeat="item in visibleItems" ng-style="{'background-color': item.color}">
            {{item.name}}
          </div>
        </div>
      </div>
    </div>

    但正如您在输出中看到的那样,这些动作似乎并不完全无缝。这是因为仓位设置并没有达到应有的安静状态。如前所述,我对 Angular 动画的工作原理知之甚少,因此我无法完全修复它们,但对进入、离开和移动使用相同的位置属性将是一个起点。如果我们在事件过程中将位置从left 修改为right 或反之亦然,transition 效果将失效,只会导致瞬间跳跃。使用 sn-p 您要注意的另一件事是,我还修改了定位值以使效果看起来更平滑。但这些都是在反复试验的基础上完成的。我强烈建议您首先使用纯 CSS 实现整个事情,然后将其移植到 AngularJS。

    (function() {
      var app = angular.module("animationApp", ["ngAnimate"]);
    
      app.controller('FrameController', ['$scope', function($scope) {
       
        $scope.message = 'Hello world';
        $scope.items = [];
        $scope.visibleItems = [];
        for (var i = 3; i < 9; i++) {
          $scope.items.push({
            name: 'Item ' + (i - 2),
            color: "#" + (i) + "0" + (i % 5) + "0" + (i % 4) + '0'
          });
        }
    
    
        $scope.firstThree = true;
        $scope.selectNextItems = function() {
          if ($scope.firstThree) {
            $scope.firstThree = false;
            $scope.visibleItems = [$scope.items[0], $scope.items[1], $scope.items[2]];
          } else {
            $scope.firstThree = true;
            $scope.visibleItems = [$scope.items[3], $scope.items[4], $scope.items[5]];
          }
        }
        $scope.selectNextItems();
      }]);
    })()
    .item-container {
      width: 400px;
      border: 1px solid red;
      overflow:hidden;
      white-space: nowrap;
    }
    .item {
      color: white;
      width: 100px;
      height: 150px;
      border: 5px solid #F3F5F6;
      display: inline-block;
      position: relative;
      cursor: pointer;
    }
    .item:hover {
      padding: 2px;
      border: 3px solid blue;
    }
    
    /* Animations */
    .item.ng-move,
    .item.ng-enter,
    .item.ng-leave {
      transition: 1400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    }
    .item.ng-enter,
    .item.ng-move {
      left: -80%;
    }
    .item.ng-enter.ng-enter-active,
    .item.ng-move.ng-move-active {
      left: 0%;
    }
    .item.ng-leave {
      left: -80%;
    }
    .item.ng-leave.ng-leave-active {
      left: 0%;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.min.js"></script>
    <div ng-app="animationApp">
      <div ng-controller="FrameController as vm">
    
        <button ng-click="selectNextItems()">Next Page</button>
    
        <div class="item-container">
    
          <div class="item" ng-repeat="item in visibleItems" ng-style="{'background-color': item.color}">
            {{item.name}}
          </div>
        </div>
      </div>
    </div>

    【讨论】:

    • white-space: nowrap 是我所需要的。我将更多地处理动画。我给出的400px 示例只是为了确保该示例在所有屏幕尺寸上都显示了该问题。我的实际项目容器将是 100% 宽度,所以我必须对如何让项目在屏幕上设置动画进行创意。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多