0

使用事例

jmpressロードする前に DOM を構築する必要があります。AngularJS を使用すると、DOM をテンプレートで構築しjmpress、DOM を監視するディレクティブで初期化できます。

DOM の読み込み中にデータが読み込まれると、つまりハードコードされたデータがイベントでjmpressトリガーされる$(document).ready()と、目的の効果が観察されます。jsfiddleを参照してください。

ただし、データが AJAX リクエストを介してロードされjmpress、ウォッチを介してトリガーされる場合、座標および回転属性は によって無視されjmpressます。

問題

テンプレートが構築される前に時計が起動すると思われるためjmpress、DOM の座標と回転が空白であることがわかります。

質問

  • jmpressangularテンプレートで作成された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();
    });
  };
});

これにより、DOM が Angular によって操作された後、ただしブラウザーがレンダリングする前まで、コードの実行が遅延されます。

デモ - $evalAsync: http://jsfiddle.net/CV2JQ/

レンダリング後にコードを実行する必要がある場合 (プラグインによって異なります)、代わりに$timeoutサービスを挿入して使用できることを知っておくとよいでしょう。

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

デモ - $timeout: http://jsfiddle.net/c9v9G/

両方の選択肢が機能する場合、レンダリングの前にコードを実行する最初の方法を好みます。これにより、場合によってはちらつきを取り除くことができます。この場合、それは問題ではないようです。

于 2014-05-21T06:22:36.043 に答える