如何相对于导致更改的单击事件对 ng 重复项进行动画处理
How to animate ng-repeat items relative to click events causing the change
我正在尝试为用户从不同的项目集中选择项目设置动画。项目应从单击的集动画化到它在选定项目列表中的新位置。
在下面的演示中,将粉色框视为可用项,将带边框的框视为选定项的列表(蓝色框)。用户可以通过单击任一粉红色框来选择项目:
angular.module('test', ['ngAnimate'])
.controller('testCtrl', function($scope) {
$scope.products = [{}, {}, {}, {}];
$scope.purchased = [{}];
$scope.purchase = function(dir) {
$scope.direction = dir
$scope.purchased.push($scope.products.pop());
};
})
.directive('testDir', function($animate) {
return {
link: function(scope, element) {
$animate.on('enter', element, function(element, phase) {
$target = scope.direction == 'left' ? $('.stock:first') : $('.stock:last');
element.position({
my: 'center',
at: 'center',
of: $target,
using: function(pos, data) {
$(this).css(pos);
$(this).animate({
top: 0,
left: 0
});
}
});
});
}
};
});
.stock {
display: inline-block;
width: 50px;
height: 50px;
background: hotpink;
}
.stock.right {
margin-left: 100px;
}
.product {
height: 50px;
width: 50px;
border: 1px solid;
}
.purchased {
height: 60px;
margin-top: 100px;
border: 2px dotted;
}
.purchased .product {
display: inline-block;
margin: 5px;
background: dodgerblue;
}
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular-animate.js"></script>
<div ng-app="test" ng-controller="testCtrl">
<div class="stock" ng-click="purchase('left')"></div>
<div class="stock right" ng-click="purchase('right')"></div>
<div class="purchased clearfix">
<div class="product" ng-repeat="product in purchased" data-test-dir>
</div>
</div>
</div>
嗯,它有点工作 - 但我正在使用 jQuery-ui 来找出起始位置(粉红色框的位置在响应式设计中会很谨慎)和 jquery animate 方法来对元素进行动画处理。
此外,我还必须将单击的方向存储在范围内,并且我在enter
事件侦听器中设置初始位置和动画以结束位置。
我一直在阅读和尝试很多关于角度内置动画钩子的实验,但找不到一种正确的方法来从相对/动态位置对元素进行动画处理。
有没有更好的方法以角度js方式实现相同的用户体验..?
正确理解了你的问题(如果没有,请告诉我); 我认为处理问题的一种方法是这样的:
同时假设产品的大小(宽度)恒定 - 设置为50px或其他东西 - ; 您可以将粉红色元素的位置设置为绝对值; 然后对粉红色元素使用 ng-repeat,并在 HTML 中包含一个简短的 ng style 属性,如下所示:
<div ng-repeat="item in products" ng-style="{'left': $index*50 + 'px'}" ng-click="add-to-purchased($index)"></div>
关于购买的产品:在"添加到购买"功能中,您可以在将产品推送到"购买"数组后,简单地将产品动画化到"顶部:'到边框元素的高度距离'"和"左"等于{$scope.purchased.length*50 + 'px'}。 然后使用 ng-class(带有切换)添加一个类来着色和其他 CSS 内容......(你也可以考虑颜色变化的过渡。
我还认为您可以使用 ng 类来处理不同的高度和顶部问题(如果产品数量超过一行的容量),该类根据以下($index>某个数字)添加具有新"top"值的类,以及另一个用于上层元素的 ng 类(位于边框元素顶部的元素),更改其高度......
我希望这是有帮助的
更新:
不幸的是,我还没有很好地理解这个问题。 但是现在看看这个问题,我认为有一种方法可以更动态地做到这一点。
在 $scope.purchase
函数中,您可以使用 $broadcast
发送指令并像这样传递点击的元素(对于库存中的任何元素,无论是否使用 ng-repeat 创建):
<div class="stock" ng-click="purchase($event)"></div>
和:
$scope.purchase = function(event) {
$scope.purchased.push($scope.products.pop());
$scope.$broadcast('purchaseHappened', event.target);
};
在你的指令中,放置事件侦听器:
scope.$on('purchaseHappened', function(event, target) {
//catch target in here, and then use it's position to animate the new elements...
})
我认为你也可以使用 target.getBoundingClientRect()
来获取元素的位置,相对于视口(.top
、.left
,...),而不是 jquery-ui 的.position
,如果你愿意......
它更接近解决方案吗?
此解决方案是一项改进,因为它消除了在 Purchase 函数中向范围添加信息的需要,并且通过使用"source"指令并将源信息存储在控制器属性中来避免混合模型数据和 UI 详细信息。 该示例已简化,当然可以改进。关键点是,管理流程所需的数据永远不会通过范围公开。
如果目标元素需要从 DOM 中删除(即它是 ng-repeat 的一部分),则必须稍微修改此解决方案以计算动画起始位置并将其存储为 monitor.click 处理程序的一部分,而不是存储目标元素本身。
在我看来,动画的方法是任意的。 此示例使用 OP 的 jqueryUI 动画方法,但它与 css 过渡或使用$animate同样有效。
一个完整的例子在这里
angular.module('app', [])
.controller('main', function($scope) {
$scope.products = [{},{}];
$scope.purchased = [{}];
$scope.Purchase = function() {
$scope.purchased.push({});
};
})
.directive('source', function(){
return {
controller: function($scope) {
}
};
})
.directive('originator', function(){
return{
require: '^source',
priority: 1,
link:{
pre: function(scope, element, attr, ctrl){
element.on('click', function(evt){
ctrl.target = evt.target;
});
}
}
};
})
.directive('sink', function(){
return {
require: '^source',
link: function(scope, element, attr, ctrl){
var target = ctrl.target;
if(target){
var $target = $(target);
//animate from target to current position
element.position({
my: 'center',
at: 'center',
of: $target,
using: function(pos, data) {
$(this).css(pos);
$(this).animate({
top: 0,
left: 0
});
}
});
ctrl.target = undefined;
}
}
};
});
- AngularJS ng重复处理空列表事例
- ng单击不处理<李>要素
- jQuery无法处理ng个重复结果
- 使用AngularJS处理嵌套ng重复.无法通过ng单击来获取按钮
- 处理ng重复中的重复元素
- 您如何处理指令和控制器中的模板 ng-click
- 当 ng 模型输入为数字时,处理它
- 为什么在单元测试中注入“ng”会改变承诺处理行为
- AngularJS - 处理错误错误:[ng:areq] 在此特殊情况下 (?)
- jQuery .focus() 无法使用 ng-repeat (AngularJS) 处理动态生成的列表项
- 如何相对于导致更改的单击事件对 ng 重复项进行动画处理
- ng显示不处理嵌套的ng重复
- 硒点击不't处理angularjs ng点击事件
- ng范围外的路线处理
- 向angularjs中的重复元素添加ng点击处理程序
- 重构angular ng资源错误处理
- ng使用服务器端处理在数据表中进行剪辑
- JQuery 无法处理 ng-view 中的元素
- 如何编写挂钩到ng-click处理程序的指令
- Ng点击并显示don'不处理动态内容(角度)