Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
592 views
in Technique[技术] by (71.8m points)

angularjs - How can I animate sorting a list with orderBy using ng-repeat with ng-animate?

I'm rendering a list of objects using ng-repeat with an orderBy filter like this:

<li class="list-item" ng-repeat="item in items | orderBy:predicate:reverse">

My attempts to ng-animate a change in sorting of the list have proven frustrating and aren't worth sharing. I have seen the Yearofmoo example app here.

Unfortunately this demonstration is not quite what I'm trying to achieve. I need to animate the X position of a given list item when it is placed in a new order after the orderBy definition changes. I have tried to accomplish this with css transitions and absolute positioning, but ng-repeat seems to recreate the list items on orderBy making animation a real challenge.

  1. Is this possible with ng-repeat | orderBy (with or without ng-animate)?
  2. Can you suggest an approach or provide an example?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So, even if @Alex Osborn has shown a way to do what you want in the comments, here is my attempt:

angular.module('StackApp', []).controller('MainCtrl', function($scope) {
  'use strict';

  $scope.reverse = 'false';

  $scope.myList = [{
    id: 0,
    text: 'HTML5 Boilerplate'
  }, {
    id: 1,
    text: 'AngularJS'
  }, {
    id: 2,
    text: 'Karma'
  }, {
    id: 3,
    text: 'Hello'
  }, {
    id: 4,
    text: 'World'
  }, {
    id: 5,
    text: 'How'
  }, {
    id: 6,
    text: 'Are'
  }, {
    id: 7,
    text: 'You'
  }, {
    id: 8,
    text: '?'
  }, {
    id: 9,
    text: 'I'
  }, {
    id: 10,
    text: 'write'
  }, {
    id: 11,
    text: 'more'
  }, {
    id: 12,
    text: 'to'
  }, {
    id: 13,
    text: 'make'
  }, {
    id: 14,
    text: 'the'
  }, {
    id: 15,
    text: 'list'
  }, {
    id: 16,
    text: 'longer'
  }];

  $scope.$watch('reverse', function() {
    $scope.setOrder();
  });

  $scope.setOrder = function() {

    if ($scope.reverse === 'random') {

      var t = [];

      for (var i = 0; i < $scope.myList.length; i++) {
        var r = Math.floor(Math.random() * $scope.myList.length);
        while (inArray(t, r)) {
          r = Math.floor(Math.random() * $scope.myList.length);
        }
        t.push(r);
        $scope.myList[i].order = r;
      }

    } else {

      for (var i = 0; i < $scope.myList.length; i++) {
        if ($scope.reverse === 'false') {
          $scope.myList[i].order = i;
        } else {
          $scope.myList[i].order = ($scope.myList.length - 1 - i);
        }
      }
    }
  };

  function inArray(a, value) {
    for (var i = 0; i < a.length; i++) {
      if (a[i] === value) {
        return true;
      }
    }
    return false;
  }

});
#list {
  /* Needed, otherwise items would be at top of the page (see below) */
  position: absolute;
  /* full width, or it would look strange */
  width: 100%;
}
#list li {
  position: absolute;
  /* Top: 0; this will be changed for every single list item by AngularJS */
  top: 0;
  /* Item height; hold this in sync with template file */
  height: 40px;
  /*  Simple transition */
  -webkit-transition: top 0.5s ease-in-out;
  -moz-transition: top 0.5s ease-in-out;
  transition: top 0.5s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="StackApp">
  <div ng-controller="MainCtrl">
    <h1>Animate Order</h1>
    <form action="">
      <label for="reverse">reverse = true</label>
      <br>
      <input type="radio" value="true" name="reverse" ng-model="reverse">
      <br>
      <br>
      <label for="reverse">reverse = false</label>
      <br>
      <input type="radio" value="false" name="reverse" ng-model="reverse">
      <br>
      <br>
      <label for="reverse">reverse = random (click button below to shuffle again)</label>
      <br>
      <input type="radio" value="random" name="reverse" ng-model="reverse">
    </form>
    <br>
    <br>
    <input type="button" ng-click="reverse = 'random';setOrder()" value="setOrder()">
    <br>
    <br>
    <ul id="list" ng-style="{height: ((myList.length * 40) + 'px')}">
      <li ng-repeat="item in myList" ng-style="{top: ((item.order * 40) + 'px')}">{{$index}} - {{item.order}}. {{item.text}}</li>
    </ul>
  </div>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...