用于平滑排序 ng-repeat 的 ngAnimate 示例? [英] Example of ngAnimate for smoothly sorting an ng-repeat?

查看:18
本文介绍了用于平滑排序 ng-repeat 的 ngAnimate 示例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想看一个使用 angular-animate (1.2x) 对列表进行排序的功能示例.(我只在互联网上遇到过坏掉的小提琴等):

I would like to see a functional example of using angular-animate (1.2x) to sort a list. (I have only come across broken fiddles etc on the interwebs):

给定数组 [A,B,C] 和后来的 [C, B, A] 的 ng-repeat 应该:

An ng-repeat given an array [A,B,C] and later [C, B, A] should:

  • 将 A 移到底部
  • 将 C 移到顶部
  • 保持B的位置

(使用 CSS 绝对顶部定位或类似方法.)

(Using CSS absolute top positioning or similar.)

一个使用交错(过渡延迟)的例子是一个奖励.

An example using staggering (transition-delay) is a bonus.

推荐答案

问题

实现你想要的可能有点棘手.

The problem

Achieving what you want can be a bit tricky.

一个常见的尝试是使用 ng-style 根据元素在列表中的索引来计算元素的位置:

A common attempt is to use ng-style to calculate the element´s position based on its index in the list:

<div ng-repeat="c in countries | orderBy:q" ng-style="{ 'top': $index * 20 + 'px' }">

演示: http://plnkr.co/edit/anv4fIrMxVDWuov6K3sw?p=预览

问题是只有一些元素是动画的,而且只向底部移动.

The problem is that only some elements are animated, and only towards the bottom.

这是为什么?

考虑以下按名称排序的列表(类似于上面演示中的列表):

Consider the following list sorted by name (similar to the one from the demo above):

  • 2 - 丹麦
  • 3 - 挪威
  • 1 - 瑞典

当您按 id 对这个列表进行排序时,只有一个元素会移动 - 瑞典从下到上.实际发生的是瑞典元素从 DOM 中移除并再次插入到其新位置.然而,当一个元素被插入到 DOM 中时,相关的 CSS 转换通常不会发生(我说通常是因为它最终取决于所讨论的浏览器是如何实现的).

When you sort this list by id instead only one element will move - Sweden from bottom to top. What actually happens is that the Sweden element is removed from the DOM and inserted again at its new position. However, when an element is inserted into the DOM the associated CSS transtions will normally not occur (I say normally as it ultimately depends on how the browser in question is implemented).

另外两个元素保留在 DOM 中,获得新的 top 位置并且它们的过渡是动画的.

The other two elements remain in the DOM, get new top positions and their transitions are animated.

因此,通过这种策略,过渡仅针对实际上并未在 DOM 中移动的元素进行动画处理.

So with this strategy the transitions are only animated for the elements that didn't actually move in the DOM.

另一种策略是包含 ngAnimate 模块并使用该 CSS 类 ng-move.几乎所有动画 ng-repeat 的例子都使用这个.

Another strategy is to include the ngAnimate module and use that CSS class ng-move. Almost all examples of animated ng-repeats use this.

但是,这将不起作用,原因有两个:

However, this will not work because of two reasons:

  1. ng-move 类将仅应用于移动的元素(因此仅应用于上面示例中的瑞典元素)

  1. The ng-move class would only be applied to the elements that move (so only to the Sweden element in the example above)

ng-move 类在元素插入到 DOM 中的新位置后应用于该元素.您可以使用 CSS 显示从不透明度 0 到 1 设置动画",但不能设置从旧位置到新位置设置动画",因为旧位置未知,每个元素必须移动不同的距离.

The ng-move class is applied to the element after it has been inserted into its new position in the DOM. You can have CSS that says "animate from opacity 0 to 1", but you can't have "animate from old position to new" since the old position is not known and each element would have to move a different distance.

解决方案

我过去使用过的一个解决方案是使用 ng-repeat 来呈现列表,但从未真正使用底层数据.这样所有的 DOM 元素都将保留在 DOM 中并且可以进行动画处理.要正确呈现元素,请使用 ng-style 和自定义属性,例如:

A solution

A solution I've used myself in the past is to use ng-repeat to render the list but never actually resorting the underlying data. This way all the DOM elements will remain in the DOM and can be animated. To render the elements correctly use ng-style and a custom property, for example:

ng-style="{ 'top': country.position * 20 + 'px' }"

要更新 position 属性,请执行以下操作:

To update the position property do the following:

  1. 创建基础数据的副本

  1. Create a copy of the underlying data

您可以使用 angular.copy 来复制整个数组,但是对于大型数组,这对性能不利.这也是不必要的,因为复制的数组中的每个对象只需要一个唯一的属性和要排序的属性:

You could use angular.copy to copy the entire array, but with large arrays this wouldn't be good for performance. It would also be unnecessary since each object in the copied array would only need a property that is unique and the property to sort by:

var tempArray = countries.map(function(country) {
  var obj = {
    id: country.id
  };
  obj[property] = country[property];
  return obj;
});

在上面的例子中,id 是唯一属性,property 是一个变量,包含要排序的属性的名称,例如 name.

In the example above id is the unique property and property is a variable containing the name of the property to sort by, for example name.

对副本进行排序

使用带有比较函数的 Array.prototype.sort() 对数组进行排序:

To sort the array use Array.prototype.sort() with a compare function:

tempArray.sort(function(a, b) {
  if (a[property] > b[property])
    return 1;
  if (a[property] < b[property])
    return -1;
  return 0;
});

  • 将位置设置为排序副本中元素的索引

  • Set position to the element's index in the sorted copy

    countries.forEach(function(country) {
      country.position = getNewPosition(country.id);
    });
    
    function getNewPosition(countryId) {
      for (var i = 0, length = tempArray.length; i < length; i++) {
        if (tempArray[i].id === countryId) return i;
      }
    }
    

  • 还有改进的余地,但这是它的基础.

    There is room for improvement, but that is the basics of it.

    演示: http://plnkr.co/edit/2Ramkg3sMW9pds9ZF1oc?p=预览

    我实现了一个使用惊人的版本,但它看起来有点奇怪,因为元素会暂时相互重叠.

    I implemented a version that used staggering, but it looked a bit weird since elements would overlap each other momentarily.

    这篇关于用于平滑排序 ng-repeat 的 ngAnimate 示例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆