0

用例

jmpress要求在加载之前构建 DOM。使用 AngularJS,可以使用模板构建 DOM,并jmpress使用监视 DOM 的指令进行初始化。

当在 DOM 加载期间加载数据,即硬编码数据并jmpress在事件上触发时$(document).ready(),观察到所需的效果。见jsfiddle

但是,当数据通过 AJAX 请求加载并jmpress通过手表触发时,坐标和旋转属性将被忽略jmpress

问题

我怀疑手表在模板构建之前触发,所以jmpress看到 DOM 中的坐标和旋转是空白的。

问题

  • 有没有办法jmpress使用角度模板创建的 DOM 中的坐标和旋转?
  • 在链接函数中添加坐标和旋转作为属性而不是使用模板会更好吗?

代码

创建了一个使用 AJAX 请求的jsFiddle 。

模板

<div ng-app="app" ng-controller="randomData" ui-impress>
    <div ng-repeat="item in data"
         class="step"
         data-duration="2000"
         data-x="{{ item.coordinates.x }}"
         data-y="{{ item.coordinates.y }}"
         data-z="{{ item.coordinates.z }}"
         data-rotate-x="{{ item.rotate.x }}"
         data-rotate-y="{{ item.rotate.y }}"
         data-rotate-z="{{ item.rotate.z }}"
         data-scale="{{ item.scale }}"
    >
        {{ item.message }}
    </div>
</div>

CSS

.step {
    opacity: 0.1;
    width: 20em;
    height: 3em;
}

.step.active {
    -webkit-transition: opacity 1s;
    -moz-transition:    opacity 1s;
    -ms-transition:     opacity 1s;
    -o-transition:      opacity 1s;
    transition:         opacity 1s;

    opacity: 1;
}

指示

var app = angular.module("app", []);

app.directive('uiImpress', function() {
    return {
        restrict: 'A',
        scope: false,
        link: function($scope, $element) {            
            var init = $scope.$watch('data', function(data) {
                if (data) {
                    $($element).children('.step').each(function(index, step) {
                        $($element).jmpress('init', step);
                    });

                    $($element).jmpress();
                    init();
                };
            });
        }
    };
});

控制器

基本上,只是一个随机数据生成器。

function randomData($scope, $http) {
    $scope.data;

    var slides = 10;

    var config = {
        coordinates: [ -1000, 1000 ],
        rotate: [ -180, 180 ],
        scale: [ 0.1, 10 ]
    };

    var randomDataSource = "http://api.icndb.com/jokes/random/" + slides;

    function getRandomInt (min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function generateData(messages) {
        return _.range(slides).map(function(value, index) {
            return {
                message: messages[index],
                coordinates : {
                    x: getRandomInt.apply(null, config.coordinates),
                    y: getRandomInt.apply(null, config.coordinates),
                    z: getRandomInt.apply(null, config.coordinates)
                },
                rotate: {
                    x: getRandomInt.apply(null, config.rotate),
                    y: getRandomInt.apply(null, config.rotate),
                    z: getRandomInt.apply(null, config.rotate)
                },
                scale: getRandomInt.apply(null, config.scale)
            };
        });
    }

    $http.get(randomDataSource).then(function(response) {
        var messages = response.data.value.map(function(item) {
            return item.joke;
        });
        $scope.data = generateData(messages);
    })
};
4

1 回答 1

1

$watch的侦听器函数中,删除以下代码:

$($element).children('.step').each(function(index, step) {
  $($element).jmpress('init', step);
});

将剩余的代码包装在一个$evalAsync调用中:

var unregister = $scope.$watch('data', function(data) {
  if (data) {

    $scope.$evalAsync(function() {
      $($element).jmpress();
      unregister();
    });
  };
});

这会延迟代码执行,直到 Angular 操作 DOM 之后,但在浏览器呈现之前。

演示 - $evalAsync:http: //jsfiddle.net/CV2JQ/

很高兴知道,如果您需要在渲染后执行代码(取决于插件),您可以注入并使用$timeout服务:

$timeout(function () {
  $($element).jmpress();
  init();
});

演示 - $timeout:http: //jsfiddle.net/c9v9G/

如果两种选择都有效,我更喜欢第一种,因为它在渲染之前执行代码,在某些情况下可以消除闪烁。在这种情况下,它似乎并不重要。

于 2014-05-21T06:22:36.043 回答