html - CSS滑入滑出动画溢出问题

标签 html css angularjs css-animations ng-animate

我正在尝试对屏幕外的图 block 列表进行动画处理,同时对屏幕上的新图 block 列表进行动画处理。

我使用 Angular 的 ng-for 来循环访问一系列可见项,因此技术上只有一个列表,但 Angular 的 ngAnimate 模块会保留被逐出的项一直存活到动画完成为止。

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

这就是正在发生的事情:

Image

这就是我想要它做的事情:

enter image description here

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

这是一个 fiddle 的工作示例: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>

最佳答案

您面临的问题是因为内容被包裹在父容器中。父容器的宽度仅为 400 像素,但每个框的宽度为 100 像素 + 2 * 5 像素(边框)。因此,同一行中只能容纳 3 个盒子,其余的必须绕到下一行。当您使所有 6 个元素同时可见时,这一点可以非常清楚地看到。正如您在下面的代码片段中看到的,最后 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>


但正如您在输出中看到的,这些 Action 似乎不太无缝。其原因是因为位置设置并不安静。如前所述,我对 Angular 动画的工作原理知之甚少,因此无法完全修复它们,但对进入、离开和移动使用相同的位置属性将是一个起点。如果我们在事件过程中将位置从 left 修改为 right 或反之亦然,则 transition 效果将失效,并且只是导致瞬间跳跃。您在代码片段中需要注意的另一件事是,我修改了定位值,以使效果看起来更平滑。但这些都是在反复试验的基础上完成的。我强烈建议您首先使用纯 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>

关于html - CSS滑入滑出动画溢出问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34730243/

相关文章:

javascript - 为使用节点appendChild添加的列表创建事件监听器

javascript - 如何让jquery显示和隐藏图像

javascript - 如何从另一个 Controller 调用一个 Controller 的功能

javascript - 为什么我的 Angular 拦截器没有正确缩小?

javascript - 由于全屏固定 Bootstrap 模式,无法单击浏览器垂直滚动条

javascript - 如何在使用 cookie 和本地存储的网站上遵守 GDPR?

jquery - body 上的 CSS 变换搞乱了固定的导航栏

jquery - CSS 更大的可点击 href 区域

angularjs - 如何使用 AngularJS 以相反的顺序导航树

javascript - css滚动内容阴影效果