2013-05-08 10 views
29

Tôi render một danh sách các đối tượng sử dụng ng-repeat với một bộ lọc orderBy như thế này:Làm cách nào để tạo animate một danh sách với orderBy bằng cách sử dụng ng-repeat với ng-animate?

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

nỗ lực của tôi để ng-động một sự thay đổi trong việc phân loại của danh sách đã chứng minh bực bội và không phải là giá trị chia sẻ . Tôi đã thấy ứng dụng ví dụ Yearofmoo here.

Thật không may, cuộc biểu tình này không hoàn toàn là những gì tôi đang cố gắng đạt được. Tôi cần tạo hiệu ứng cho vị trí X của một mục danh sách đã cho khi nó được đặt theo thứ tự mới sau khi thay đổi định nghĩa orderBy. Tôi đã cố gắng thực hiện điều này với chuyển tiếp css và định vị tuyệt đối, nhưng ng-repeat dường như tạo lại các mục danh sách trên orderBy làm cho hoạt hình trở thành một thách thức thực sự.

  1. Điều này có thể với ng-repeat | orderBy (có hoặc không có ng-animate)?
  2. Bạn có thể đề xuất phương pháp tiếp cận hoặc cung cấp ví dụ không?
+5

Tôi đã gặp vấn đề này nhưng chưa có để xây dựng một giải pháp, hoặc tôi sẽ cung cấp một câu trả lời thích hợp với các ví dụ - tuy nhiên giải pháp tôi đã lên kế hoạch là lọc một bản sao của danh sách (ví dụ trong bộ điều khiển), tìm chỉ mục mới của mục, sau đó chuyển động mục đó sang chỉ mục đó. Bạn nói đúng - bộ lọc + ng-lặp lại chỉ cần xây dựng lại danh sách. Những gì bạn thực sự muốn là riêng biệt xác định vị trí từ chế biến các hình ảnh động. –

+0

Tôi sợ rằng có thể là giải pháp - cảm ơn! – Casey

+0

@AlexOsborn Bạn nên gửi câu trả lời đó làm câu trả lời. Nó đã giúp đỡ tôi! –

Trả lời

41

Vì vậy, ngay cả khi @ Alex Osborn đã cho thấy một cách để làm những gì bạn muốn trong các ý kiến, đây là nỗ lực của tôi:

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>

Vì vậy, AngularJS không đặt hàng các mặt hàng, nhưng nó thay đổi thuộc tính CSS top (ng-style="{top: ...}"). AngularJS không tái tạo danh sách và chúng tôi có được một hình ảnh động đẹp mắt. :)

+0

Cảm ơn bạn đã kết hợp điều này! – Casey

+6

Lưu ý rằng giải pháp này chỉ thay đổi các thuộc tính kiểu 'top' của các phần tử, không phải thứ tự của chúng trong DOM (có lẽ là tại sao nó hoạt động - các phần tử không bị loại bỏ và được readded bởi Angular). Mặc dù điều này không quan trọng bằng mắt thường nhưng không tốt cho khả năng truy cập: người dùng khiếm thị với trình đọc màn hình sẽ luôn nhận được thứ tự ban đầu của lần hiển thị đầu tiên. Xem hướng dẫn WCAG về chủ đề này: http://www.w3.org/TR/WCAG20-TECHS/C27.html – denisw

+0

Thay vào đó, viết So Much of Code bạn có thể trực tiếp sử dụng hàm reverse() của javascript. var list = CompanyList []; reverselist = list.đảo ngược(); ng-repeat = "mục trong danh sách đảo ngược" –

11

Tôi đã mở rộng khi câu trả lời của AndreM96 cho phép hiển thị danh sách dưới dạng lưới.

angular.module('StackApp', []).config(function($routeProvider) { 
 

 
    'use strict'; 
 

 
    $routeProvider 
 
    .when('/', { 
 
     template: '<h1>Animate Order</h1>' + 
 
     '<form action="">' + 
 
     '<input type="radio" value="true" name="order" ng-model="order">' + 
 
     '<label for="order">reverse</label><br><br>' + 
 

 
     '<input type="radio" value="false" name="order" ng-model="order">' + 
 
     '<label for="order">normal</label><br><br>' + 
 

 
     '<input type="radio" value="random" name="order" ng-model="order">' + 
 
     '<label for="order">random (click button below to shuffle again)</label><br>' + 
 

 
     '</form>' + 
 
     '<input type="button" ng-click="order = \'random\';setOrder()" value="randomize">' + 
 
     '<br><br>' + 
 
     '<ul id="list" ng-style="{height: ((myList.length * 90) + \'px\')}">' + 
 
     '<li ng-repeat="item in myList" ng-style="{top: ((item.row * 90) + \'px\'), left: ((item.column * 90) + \'px\')}">{{$index}} - {{item.order}}. {{item.text}}</li>' + 
 
     '</ul>', 
 
     controller: 'MainCtrl' 
 
    }) 
 
    .otherwise({ 
 
     redirectTo: '/' 
 
    }); 
 

 
}); 
 

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

 
    $scope.order = '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('order', function() { 
 
    $scope.setOrder(); 
 
    }); 
 

 
    $scope.setOrder = function() { 
 

 
    var i; 
 

 
    if ($scope.order === 'random') { 
 
     var t = []; 
 
     for (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 if ($scope.order === 'false') { 
 
     for (i = 0; i < $scope.myList.length; i++) { 
 
     $scope.myList[i].order = i; 
 
     } 
 
    } else { 
 
     for (i = 0; i < $scope.myList.length; i++) { 
 
     $scope.myList[i].order = ($scope.myList.length - 1 - i); 
 
     } 
 
    } 
 

 
    calcGridPosition(); 
 
    }; 
 

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

 
    function calcGridPosition() { 
 
    for (var i = 0; i < $scope.myList.length; i++) { 
 
     var item = $scope.myList[i]; 
 

 
     // columns, left-to-right, top-to-bottom 
 
     var columns = 5; 
 
     item.column = item.order % columns; 
 
     item.row = Math.floor(item.order/columns); 
 

 
     // rows, top-to-bottom, left-to-right 
 
     // var rows = 3; 
 
     // item.column = Math.floor(item.order/rows); 
 
     // item.row = item.order%rows; 
 
    } 
 
    } 
 

 
});
#list { 
 
    position: absolute; 
 
    width: 100%; 
 
    list-style-type: none; 
 
    padding-left: 0; 
 
} 
 

 
#list li { 
 
    position: absolute; 
 
    height: 70px; 
 
    width: 70px; 
 
    background: #ddd; 
 
    -webkit-transition: all 2.5s ease-in-out; 
 
    -moz-transition: all 2.5s ease-in-out; 
 
    transition: all 2.5s ease-in-out; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script> 
 
<main ng-app="StackApp"> 
 
    <div class="container" ng-view></div> 
 
</main>

JSBin Demo

enter image description here

+1

vì vậy mã của đâu? – krivar

+8

Nhấp vào liên kết 'xem demo' ở trên và bạn sẽ thấy nút 'chỉnh sửa trong js bin' ở góc trên bên phải của trình duyệt. PS: Câu hỏi của bạn nghe có vẻ thô lỗ. Tôi sẽ đánh giá cao nếu bạn muốn hỏi nhiều hơn thời gian tiếp theo. Cảm ơn. – robro

+0

xin cảm ơn vì đã trả lời và phản hồi cho nhận xét của tôi. Tôi sẽ chăm sóc cẩn thận lần sau. – krivar