74

クイックナビを正しく動作させようとしています。横に浮いています。リンクをクリックすると、ページ上のその ID に移動します。Treehouseのこのガイドに従っています。これは私がスクロールのために持っているものです:

$("#quickNav a").click(function(){
    var quickNavId = $(this).attr("href");
    $("html, body").animate({scrollTop: $(location).offset().top}, "slow");
    return false;
});

最初は の前に配置しました</body>。しかし、quickNavがコンパイルされる前に発火していた競合状態に陥っているようです(それがng-hide原因であるかどうかはわかりませんが、DOM内にあります)。

そのコード ブロックをコンソールで実行すると、スクロールは期待どおりに機能します。

これをコントローラーに移動するか、ディレクティブ内に移動する方が効果的であると考えました。しかし、私はそれを達成する運がありません。このコード ブロックを AngularJS で動作させるにはどうすればよいですか?

4

10 に答える 10

122

クリックすると要素にスクロールする簡単なディレクティブを次に示します。

myApp.directive('scrollOnClick', function() {
  return {
    restrict: 'A',
    link: function(scope, $elm) {
      $elm.on('click', function() {
        $("body").animate({scrollTop: $elm.offset().top}, "slow");
      });
    }
  }
});

デモ: http://plnkr.co/edit/yz1EHB8ad3C59N6PzdCD?p=preview

ディレクティブの作成については、http://egghead.ioの #10「最初のディレクティブ」から始まるビデオをご覧ください。

edit : href で指定された特定の要素までスクロールするには、チェックするだけattrs.hrefです。

myApp.directive('scrollOnClick', function() {
  return {
    restrict: 'A',
    link: function(scope, $elm, attrs) {
      var idToScroll = attrs.href;
      $elm.on('click', function() {
        var $target;
        if (idToScroll) {
          $target = $(idToScroll);
        } else {
          $target = $elm;
        }
        $("body").animate({scrollTop: $target.offset().top}, "slow");
      });
    }
  }
});

次に、次のように使用でき<div scroll-on-click></div>ます。クリックした要素までスクロールします。または<a scroll-on-click href="#element-id"></div>、id を持つ要素にスクロールします。

于 2013-06-24T21:21:13.403 に答える
32

これは、使用したい場合に適したディレクティブです。

ページ内の任意の要素にスクロールできます。

.directive('scrollToItem', function() {                                                      
    return {                                                                                 
        restrict: 'A',                                                                       
        scope: {                                                                             
            scrollTo: "@"                                                                    
        },                                                                                   
        link: function(scope, $elm,attr) {                                                   

            $elm.on('click', function() {                                                    
                $('html,body').animate({scrollTop: $(scope.scrollTo).offset().top }, "slow");
            });                                                                              
        }                                                                                    
    }})     

使用法 (たとえば、div 'back-to-top' をクリックすると、id scroll-top にスクロールします):

<a id="top-scroll" name="top"></a>
<div class="back-to-top" scroll-to-item scroll-to="#top-scroll"> 

chrome,firefox,safari および IE の html,body 要素でもサポートされています。

于 2014-07-04T15:36:47.753 に答える
23

スクロールコンテナ内の特定の要素にアニメートするため(固定DIV)

/*
    @param Container(DIV) that needs to be scrolled, ID or Div of the anchor element that should be scrolled to
    Scrolls to a specific element in the div container
*/
this.scrollTo = function(container, anchor) {
    var element = angular.element(anchor);
    angular.element(container).animate({scrollTop: element.offset().top}, "slow");
}
于 2015-02-17T09:25:22.887 に答える
6

$anchorScrollBen Lesh による現在アーカイブされているブログ投稿から取得した角度付きソリューションを使用して、これも彼が貢献したこの SO 回答で詳細に再現されています(ルーティング内でこれを行う方法の書き直しを含む):

app.controller('MainCtrl', function($scope, $location, $anchorScroll) {
  var i = 1;
  
  $scope.items = [{ id: 1, name: 'Item 1' }];
  
  $scope.addItem = function (){
    i++;
    //add the item.
    $scope.items.push({ id: i, name: 'Item ' + i});
    //now scroll to it.
    $location.hash('item' + i);
    $anchorScroll();
  };
});

そして、これがこのソリューションを提供したブログのプランカーです: http://plnkr.co/edit/xi2r8wP6ZhQpmJrBj1jM?p=preview

そのプランカーのテンプレートにはこれが含まれていることに注意してください。これにより、スクロールにid使用しているがセットアップされます。$anchorScroll

<li ng-repeat="item in items" 
    id="item{{item.id}}"
>{{item.name}</li>

そして、純粋な JavaScript ソリューションが必要な場合は、次の 1 つがあります。

親コンテナ ID とターゲット スクロール ID を指定して、コードで runScroll を呼び出します。

function runScroll(parentDivId,targetID) {
    var longdiv;
    longdiv = document.querySelector("#" + parentDivId);
    var div3pos = document.getElementById(targetID).offsetTop;
    scrollTo(longdiv, div3pos, 600);
}


function scrollTo(element, to, duration) {
    if (duration < 0) return;
    var difference = to - element.scrollTop;
    var perTick = difference / duration * 10;

    setTimeout(function () {
        element.scrollTop = element.scrollTop + perTick;
        if (element.scrollTop == to) return;
        scrollTo(element, to, duration - 10);
    }, 10);
}

参考:クロスブラウザJavaScript(jQueryではなく…)トップへスクロールのアニメーション

于 2015-06-28T18:08:01.027 に答える
4

例をくれたアンディに感謝します。これは非常に役に立ちました。私は単一ページのスクロールを開発しており、hashbang URL を使用するときに Angular を更新したくないため、少し異なる戦略の実装を終了しました。また、ブラウザの戻る/進むアクションを保持したいと考えています。

ディレクティブとハッシュを使用する代わりに、$location.search で $scope.$watch を使用し、そこからターゲットを取得しています。これにより、きれいなアンカータグが得られます

<a ng-href="#/?scroll=myElement">My element</a>

次のように、watch コードを app.js の my module 宣言にチェーンしました。

.run(function($location, $rootScope) {
   $rootScope.$watch(function() { return $location.search() }, function(search) { 
     var scrollPos = 0;
     if (search.hasOwnProperty('scroll')) {
       var $target = $('#' + search.scroll);
       scrollPos = $target.offset().top;
     }   
     $("body,html").animate({scrollTop: scrollPos}, "slow");
   });
})

上記のコードの注意点は、別のルートから直接 URL でアクセスすると、jQuery の $target.offset() 呼び出しに間に合うように DOM がロードされない可能性があることです。解決策は、このコードを $viewContentLoaded ウォッチャー内にネストすることです。最終的なコードは次のようになります。

.run(function($location, $rootScope) {
  $rootScope.$on('$viewContentLoaded', function() {
     $rootScope.$watch(function() { return $location.search() }, function(search) {
       var scrollPos = 0 
       if (search.hasOwnProperty('scroll')) {
         var $target = $('#' + search.scroll);
         var scrollPos = $target.offset().top;
       }
       $("body,html").animate({scrollTop: scrollPos}, "slow");                                                                                                                                                                    
     });  
   });    
 })

Chrome と FF でテスト済み

于 2013-09-02T19:27:46.797 に答える
4

私はandrew joslinの答えを使用しました. ルート変更のトリガーを避けたい場合は、

myApp.directive('scrollOnClick', function() {
  return {
    restrict: 'A',
    link: function(scope, $elm, attrs) {
      var idToScroll = attrs.href;
      $elm.on('click', function(event) {
        event.preventDefault();
        var $target;
        if (idToScroll) {
          $target = $(idToScroll);
        } else {
          $target = $elm;
        }
        $("body").animate({scrollTop: $target.offset().top}, "slow");
        return false;
      });
    }
  }
});
于 2015-07-26T06:57:19.957 に答える
3

別の提案。セレクター付きの 1 つのディレクティブ。

HTML:

<button type="button" scroll-to="#catalogSection">Scroll To</button>

角度:

app.directive('scrollTo', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('click', function () {

                var target = $(attrs.scrollTo);
                if (target.length > 0) {
                    $('html, body').animate({
                        scrollTop: target.offset().top
                    });
                }
            });
        }
    }
});

$anchorScroll にも注意してください

于 2016-09-07T06:47:37.490 に答える
2

angular-scrollについてはどうですか。積極的に維持されており、jQuery への依存関係はありません。

于 2015-05-19T08:31:56.457 に答える