jquery – AngularJS:指令:动画滑动页面并推迟控制器绑定

我试图找出如何推迟默认控制器绑定并仅在指令内应用它,一旦特定动画(自定义 – 而不是
angularjs one)已经在带有内容的DOM元素上执行.我想要完成的事情就在这里,尽管它确实在滑动动画完成之前立即取代了内容:
http://jsfiddle.net/scabro/hHy7s/27/

我需要能够推迟$scope绑定,直到页面容器完成滑动/动画,然后用控制器内的数据替换内容,一旦完成,请向下滑动.

这是我现在拥有的:

HTML:

<div id="wrapper" ng-app="myApp">

    <div page-animate>

        <p>
            <a class="btn btn-primary" href="#/" ng-click="slidePage()">Home</a>
            <a class="btn btn-info" href="#/users" ng-click="slidePage()">Users</a>
            <a class="btn btn-success" href="#/pages" ng-click="slidePage()">Pages</a>
        </p>
        <div id="relativeContainer">

            <div id="content" ng-view=""></div>

        </div>

    </div>

</div>

CSS:

#wrapper {
    text-align:center;
    padding:30px 0;
}
#relativeContainer {
    text-align:left;
    position: relative;
    width: 500px;
    height: 800px;
    min-height: 800px;
    margin: 0 auto;
    overflow: hidden;
}
#content {
    position: absolute;
    top: 0;
    left: 0;
}

JS:

var myApp = angular.module('myApp', []);

myApp.directive('pageAnimate', function() {

    return {

        restrict: 'A',

        scope: { },

        link: function (scope, elem, attrs) {

            scope.slidePage = function() {

                var thisContainer = $('#content');

                var thisHeight = thisContainer.outerHeight();

                thisContainer.animate({ top : '-' + thisHeight + 'px'}, { duration : 300, complete : function() {

                    thisContainer.css({ top : '-999999em' });

                    var thisNewHeight = thisContainer.outerHeight();

                    $('#relativeContainer').animate({ height : thisNewHeight + 'px' }, { duration : 200, complete : function() {

                        thisContainer.css({ top : '-' + thisNewHeight + 'px' }).animate({ top : 0 }, { duration : 300 });

                    }});

                }});

            };

        }

    }

});


myApp.config(function($routeProvider) {

    $routeProvider
        .when('/',
            {
                controller: 'HomeController',
                template: '<h1>{{ heading }}</h1><p>{{ content }}</p>'
            }
        )
        .when('/users',
            {
                controller: 'UserController',
                template: '<h1>{{ heading }}</h1><p>{{ content }}</p>'
            }
        )
        .when('/pages',
            {
                controller: 'PageController',
                template: '<h1>{{ heading }}</h1><p>{{ content }}</p>'
            }
        )
        .otherwise(
            {
                redirectTo: '/'
            }
        )

});

myApp.controller('HomeController', function($scope) {

    $scope.heading = 'Home page';
    $scope.content = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate';

});

myApp.controller('UserController', function($scope) {

    $scope.heading = 'Users';
    $scope.content = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.';

});

myApp.controller('PageController', function($scope) {

    $scope.heading = 'Pages';
    $scope.content = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.';

});

最佳答案 首先,一些微小的变化,以获得你的工作.您需要阻止默认事件导航页面(这就是导航完成之前更改的原因),并且您需要在第一个动画完成后手动执行导航.所以一种方法是将事件和url传递给slidePage:

<div id="wrapper" ng-app="myApp">
    <div page-animate>
        <p>
            <a class="btn btn-primary"  ng-click="slidePage($event, '/')">Home</a>
            <a class="btn btn-info" ng-click="slidePage($event, '/users')">Users</a>
            <a class="btn btn-success" ng-click="slidePage($event, '#/pages')">Pages</a>
        </p>
        <div id="relativeContainer">

            <div id="content" ng-view=""></div>
        </div>
    </div>
</div>

和slidePage本身变成:

        scope.slidePage = function(event, url) {
            event.preventDefault();
            event.stopPropagation();
            var thisContainer = $('#content');

            var thisHeight = thisContainer.outerHeight();

            thisContainer.animate({ top : '-' + thisHeight + 'px'}, { duration : 300, complete : function() {
                thisContainer.css({ top : '-999999em' });
                $location.url(url);
                scope.$apply();

                var thisNewHeight = thisContainer.outerHeight();

                $('#relativeContainer').animate({ height : thisNewHeight + 'px' }, { duration : 200, complete : function() {

                    thisContainer.css({ top : '-' + thisNewHeight + 'px' }).animate({ top : 0 }, { duration : 300 });

                }});

            }});

该代码应该按照您的意愿工作,但我不认为它遵循角度哲学.

相反,我认为你应该做的是直接添加一个slidePage指令,这样链接就是< a href =’#/ pages’clip-page>.该指令可以访问属性(因此它可以获取href),并且可以将单击处理程序直接绑定到锚元素上.我还会通过用另一个指令标记要动画的元素来删除#content元素的硬连线.但是,相同的基本原则适用:停止事件传播,执行第一个动画,然后在执行第二个动画之前更新位置.

点赞