使用ng-class有条件地添加CSS3动画

时间:2014-09-24 17:31:47

标签: javascript angularjs css3 animation

我有两个CSS3动画,当我的控制器满足特定条件时,我将添加到dom中。我正在使用ng-class在满足这些条件时引入不同的动画(摇Y和摇X)。 (我只是包括相关的js):

$scope.submitAnswer = function($index) {
    ...

    if ($index == current) {
        console.log('correct!');
        $scope.shaken = 'shakeY';
    }
    else {
        console.log('incorrect!');
        $scope.shaken = 'shakeX';
    }
}

以及相关的HTML:

    <div 
        id="philosopher" 
        ng-class="shaken"
        ng-click="submitAnswer($index);" 
        ng-repeat="philosopher in philosophers">
        <img ng-src="images/{{philosopher.signifier}}.png" height="142px" width="auto" />
        <h2>{{philosopher.name}}</h2>
    </div>

这是按照我的意愿工作,然而,我发现我不能继续应用相同的动画类并让动画执行 - 我需要交替(在满足if语句和触发else之间) )。

我发现我可以使用自定义指令和ngAnimate来反复触发动画,但我不知道如何根据if else的结果实现单独的动画 这是指令之一:

app.directive('shake', function($animate) {
    return {
        restrict: 'A',
        scope: false,
        link: function(scope, element, attrs) {

            element.bind('click', function() {

                $animate.addClass(element, 'shakeX', function() {
                    $animate.removeClass(element, 'shakeX');
                });

            });
        }
    };
});

我如何不断地将shakeX和shakeY重新应用到ng-class或者我如何才能根据if else语句的结果使用我的指令?

修改

终于搞定了!感谢您的帮助,最终工作的是在if语句中以正确的方式实现超时功能。 (我从技术上知道你不应该在if语句中使用函数[我认为这是正确的吗?],但我终于让它工作了!)这基本上是我最终的结果:

    if ($index == current) {
        console.log('correct!');
        $timeout(function() {
            $scope.shaken = 'shakeY'
        })
    }
    else {
        console.log('incorrect!');
        $timeout(function() {
            $scope.shaken = 'shakeX'
        })
    }

2 个答案:

答案 0 :(得分:1)

我认为你不需要一个指令来实现你想要的。问题是当您在范围内分配相同的值时,如果范围属性的观察者具有相同的值,则不会触发该属性的观察者。您需要做的是从诱饵值或空值更改scope属性的值,然后使用$timeout将值从诱饵值更改为原始值。

这样的事情:

<强> DEMO

HTML

<div ng-class="shake" ng-click="shakeX()">Shake X</div>
<div ng-class="shake" ng-click="shakeY()">Shake Y</div>

JAVASCRIPT

$scope.shakeX = function() {
  $scope.shake = '';
  $timeout(function() {
    $scope.shake = 'shakeX';
  })
};

$scope.shakeY = function() {
  $scope.shake = '';
  $timeout(function() {
    $scope.shake = 'shakeY';
  })
};

答案 1 :(得分:0)

直接班级改变方法

通过我们在评论中的小聊天判断,听起来像动画持续时间的超时将是最好的方法。基本上,你只需要改变这个:

$animate.addClass(element, 'shakeX', function() {
    $animate.removeClass(element, 'shakeX');
});

进入这个:

$animate.addClass(element, 'shakeX', function() {
    $timeout(function() {
        $animate.removeClass(element, 'shakeX');
    }, 420);
});

不要忘记添加$timeout依赖项。

总结一下,我们的想法是在CSS动画完成后删除该类,以便在下次单击时重新分配该类。


控制器范围变量方法

或者,如果您希望从控制器获得原始方法,您可以执行类似的操作:

if ($index == current) {
    console.log('correct!');
    $scope.shaken = 'shakeY';
}
else {
    console.log('incorrect!');
    $scope.shaken = 'shakeX';
}

$timeout(function() {
    $scope.shaken = false;
}, 420);

这个只是在动画后将范围变量重置为false,而不关心它是哪个类。


链接器方法中的

$watch范围变量

这就是你如何从指令中完成整个事情,这应该在链接器函数中:

scope.$watch('shaken', function(newValue, oldValue) {

    if (newValue != 'shakeX' && newValue != 'shakeY')
        return; // just in case

    $animate.addClass(element, newValue, function() {
        $timeout(function() {
            $animate.removeClass(element, newValue);
        }, 420);
    });
});

我们会关注shaken变量的更改,并相应地应用更改。