60

ユーザーがブラウザウィンドウを特定のポイントより下にスクロールすると、#pagedivのクラスが切り替わります。

私がこれまでに行ったことはうまくいきます:

http://jsfiddle.net/eTTZj/29/

<div ng-app="myApp" scroll id="page">

    <header></header>
    <section></section>

</div>

app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {
             if (this.pageYOffset >= 100) {
                 element.addClass('min');
                 console.log('Scrolled below header.');
             } else {
                 element.removeClass('min');
                 console.log('Header is in view.');
             }
        });
    };
});

(ウィンドウをヘッダーの下にスクロールすると、100ピクセル、クラスが切り替わります)

私が間違っている場合は訂正してください。ただし、これはAngularでこれを行う正しい方法ではないと感じています。

代わりに、これを行うための最良の方法は、ng-classを使用し、スコープにブール値を格納することであると推測しました。このようなもの:

<div ng-app="myApp" scroll id="page" ng-class="{min: boolChangeClass}">

    <header></header>
    <section></section>

</div>

app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {
             if (this.pageYOffset >= 100) {
                 scope.boolChangeClass = true;
                 console.log('Scrolled below header.');
             } else {
                 scope.boolChangeClass = false;
                 console.log('Header is in view.');
             }
        });
    };
});

これは動的ではありませんが、スクロールコールバックでscope.boolChangeClassの値を変更すると、ng-classが更新されません。

だから私の質問は、ユーザーが特定のポイントの下にスクロールしたときに、AngularJSを使用して#pageのクラスを切り替えるのに最適な方法は何ですか?

4

6 に答える 6

86

彼のコメントで私の質問に答えてくれたFlekに感謝します:

http://jsfiddle.net/eTTZj/30/

<div ng-app="myApp" scroll id="page" ng-class="{min:boolChangeClass}">

    <header></header>
    <section></section>

</div>

app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {
             if (this.pageYOffset >= 100) {
                 scope.boolChangeClass = true;
             } else {
                 scope.boolChangeClass = false;
             }
            scope.$apply();
        });
    };
});
于 2013-02-14T17:43:42.307 に答える
23

なぜあなたは皆、重いスコープの操作を提案するのですか?これが「角度のある」解決策ではない理由がわかりません。

.directive('changeClassOnScroll', function ($window) {
  return {
    restrict: 'A',
    scope: {
        offset: "@",
        scrollClass: "@"
    },
    link: function(scope, element) {
        angular.element($window).bind("scroll", function() {
            if (this.pageYOffset >= parseInt(scope.offset)) {
                element.addClass(scope.scrollClass);
            } else {
                element.removeClass(scope.scrollClass);
            }
        });
    }
  };
})

したがって、次のように使用できます。

<navbar change-class-on-scroll offset="500" scroll-class="you-have-scrolled-down"></navbar>

また

<div change-class-on-scroll offset="500" scroll-class="you-have-scrolled-down"></div>
于 2016-08-04T16:07:17.513 に答える
16

これは私の解決策です。それほどトリッキーではなく、単純なng-classディレクティブを介していくつかのマークアップに使用できます。同様に、各ケースのクラスとscrollPosを選択できます。

あなたのApp.js:

angular.module('myApp',[])
    .controller('mainCtrl',function($window, $scope){
        $scope.scrollPos = 0;

        $window.onscroll = function(){
            $scope.scrollPos = document.body.scrollTop || document.documentElement.scrollTop || 0;
            $scope.$apply(); //or simply $scope.$digest();
        };
    });

あなたのindex.html:

<html ng-app="myApp">
    <head></head>
    <body>
        <section ng-controller="mainCtrl">
            <p class="red" ng-class="{fix:scrollPos >= 100}">fix me when scroll is equals to 100</p>
            <p class="blue" ng-class="{fix:scrollPos >= 150}">fix me when scroll is equals to 150</p>
        </section>
    </body>
</html>

ここでJSFiddleを動作させます

編集 :

$apply()実際に呼び出しているように、コンテキストに応じてパフォーマンスを向上させる代わりに、$rootScope.$digest()直接使用することができます。 簡単に言うと、常に機能しますが、パフォーマンスの問題を引き起こす可能性のあるすべてのスコープを 強制します。$scope.$digest()$scope.$apply()
$apply()$digest

于 2015-07-06T16:02:00.473 に答える
2

多分これは助けることができます:)

コントローラ

$scope.scrollevent = function($e){
   // Your code
}

HTML

<div scroll scroll-event="scrollevent">//scrollable content</div>

または

<body scroll scroll-event="scrollevent">//scrollable content</body>

指令

.directive("scroll", function ($window) {
   return {
      scope: {
         scrollEvent: '&'
      },
      link : function(scope, element, attrs) {
        $("#"+attrs.id).scroll(function($e) { scope.scrollEvent != null ?  scope.scrollEvent()($e) : null })
      }
   }
})
于 2016-01-21T13:00:16.170 に答える
1

パフォーマンスはどうですか?

  1. 計算を減らすために、常にイベントをデバウンスします
  2. scope.applyAsync全体的なダイジェストサイクル数を減らすために使用
function debounce(func, wait) {
    var timeout;
    return function () {
        var context = this, args = arguments;
        var later = function () {
            timeout = null;
            func.apply(context, args);
        };

        if (!timeout) func.apply(context, args);
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

angular.module('app.layout')
  .directive('classScroll', function ($window) {    
    return {
        restrict: 'A',
        link: function (scope, element) {    
            function toggle() {
                angular.element(element)
                  .toggleClass('class-scroll--scrolled', 
                    window.pageYOffset > 0);
                scope.$applyAsync();
            }    
            angular.element($window)
              .on('scroll', debounce(toggle, 50));

            toggle();
        }
    };
});

3.ウォッチャー/ダイジェストをトリガーする必要がまったくない場合は、compile

.directive('classScroll', function ($window, utils) {
    return {
        restrict: 'A',
        compile: function (element, attributes) {
            function toggle() {
                angular.element(element)
                  .toggleClass(attributes.classScroll,
                    window.pageYOffset > 0);
            }

            angular.element($window)
              .on('scroll', utils.debounce(toggle, 50));
            toggle();
        }
    };
  });

そして、あなたはそれを次のように使うことができます<header class-scroll="header--scrolled">

于 2016-10-30T01:52:37.617 に答える
-4

彼らが言うように、指令は「角のある世界の内側」ではありません。だからあなたはものを変更するときにそれに戻るために適用を使用する必要があります

于 2013-04-05T13:18:41.540 に答える