在页面重新加载时滚动页面到哈希位置 - AngularJS

时间:2014-12-22 09:30:41

标签: angularjs twitter-bootstrap

我正在使用angularJS开发一个网站,并使用Twitter bootstrap进行UI。我有一些哈希Ids与某个部分相关联,因此当用户点击导航时,页面会向下滚动到该部分。它对我来说很好。

此处网站链接:https://powerful-cliffs-1105.herokuapp.com/about

现在在页面左右。我有正确的导航,将页面滚动到特定位置。但是当我重新加载该页面时,页面从顶部开始,而不是向下滚动到hash位置,如https://powerful-cliffs-1105.herokuapp.com/about#management

针对上述问题有两种解决方案:

  1. 当我们重新加载该页面时,从URL中删除哈希标记。
  2. 在页面重新加载时将页面滚动到特定(哈希)部分。
  3. 由于我还在学习angularJS,我无法找到上述问题的任何具体解决方案。

    非常感谢任何帮助。

3 个答案:

答案 0 :(得分:7)

使用$anchorScroll服务。

这里的问题是,Angular以非常方式加载 about 内容,因此当您拥有哈希时,您没有准备好内容。 $anchorScroll跟踪哈希并为您滚动。

// Just borrow from your code    
angular.module('aboutController', []).controller('aboutController',['$scope', '$location', '$anchorScroll', 
    function($scope, $location, $anchorScroll) {

  $scope.isActive = function(route){
     return route === $location.hash();
  }

  $anchorScroll();
}]);

编辑31/12:

由于Mohit(问题的创建者)说我的解决方案对他不起作用,我决定下载代码并在本地工作。我的解决方案在本地工作,这让我感到震惊,但我想在代码中指出一些可能(或者很可能不是)可以解决问题的版本。

将脚本移动到页面底部(index.html)

<!-- ANGULAR DYNAMIC CONTENT -->
  <div class="body" ng-view></div>

  <!-- FOOTER -->
  <footer ng-include="'views/footer.html'"></footer>

  <!-- JS -->
  <script src="js/libs/angular/angular.min.js"></script>
  <script src="js/libs/angular-bootstrap/ui-bootstrap.min.js"></script>
  <script src="js/libs/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
  <script src="js/libs/angular-route/angular-route.min.js"></script>

  <!-- ANGULAR CUSTOM CONTROLLERS -->
  <script src="js/controllers/home.js"></script>
  <script src="js/controllers/about.js"></script>
  <script src="js/controllers/contact.js"></script>

  <!-- ANGULAR CUSTOM FACTORIES -->
  <script src="js/services/contact.js"></script>

  <!-- UTILITY FILE -->
  <script src="js/utils/util.js"></script>

  <!-- ANGULAR CUSTOM ROUTES AND APP -->
  <script src="js/route-provider.js"></script>
  <script src="js/app.js"></script>
</body>

现在删除/评论html5Mode(route-provider.js)

// $locationProvider.html5Mode(true);

并在访问网址like this

之前附加/#/

暂停

这是我不建议的那个,但你当然可以试一试

$timeout(function() {
    $anchorScroll(); 
}, 0)

答案 1 :(得分:1)

您可以使用指令并在其中查看范围值:

var app = angular.module('plunker', ['LocalStorageModule']);

app.controller('MainCtrl', [ '$scope', 'localStorageService', function($scope, localStorageService) {
  if(localStorageService.isSupported) {
    $scope.util = localStorageService.get('anchor');
    console.log(localStorageService.get('anchor'));
  }
  else{
    $scope.util = "third";
  }

  $scope.moveTo = function(anchor){
    console.log('controller anchor value:', anchor);
    $scope.util = anchor;
    if(localStorageService.isSupported) {
      localStorageService.set('anchor', anchor);
    }
  };


}]);

app.directive('scrollToAnchor', ['$location', '$anchorScroll', function($location, $anchorScroll){
  return{
    restrict: 'A',
    scope: {
      anchor: '='
    },
    link: function(scope, element){
        scope.$watch('anchor', function(){
          $location.hash(scope.anchor);
          $anchorScroll();
          console.log('directive anchor value:', scope.anchor);
        });
    }
  };
}]);

我不知道它是否是最好的方式,但你需要在滚动到元素之前渲染你的dom。

这里是plnkr:http://plnkr.co/edit/niFzeX7XAJVNzDoD0CXa?p=preview

答案 2 :(得分:0)

在angularJS投入更多时间之后,我发现$anchorScroll将需要像@Rigoti所说的那样工作。但不知怎的,它对我不起作用。

或者,我发现我们可以使用工厂/服务创建自己的方法,或者我们也可以创建一个单独的类/对象,如实用程序文件,然后可以在角度模块中使用。 所以我创建了一个util文件并添加了一个方法来使用brettdewoody这个伟大的小提琴来提供平滑的滚动http://jsfiddle.net/brettdewoody/y65G5/

之后我修改了我的代码,以便我可以访问该方法并调用它。

<强> about.js

angular.module('aboutController', []).controller('aboutController',['$scope', '$location', '$anchorScroll', function($scope, $location, $anchorScroll) {

    // create local instance of utility object
    $scope.util = util;

    // move scroll position to passed id
    $scope.moveTo = function(id){
        // set hash location to clicked id so that isActive class is added to it.
        $location.hash(id);
        // scroll to element id
        $scope.util.scrollTo(id);
    }

    // set active class to right hand navigation on route change
    $scope.isActive = function(route){
        return route === $location.hash();
    }

    // if hash is available, scroll to hash position on page reload
    //$anchorScroll();
    if(!$scope.util.isNull($location.hash()))
        $scope.util.scrollTo($location.hash());

}]);

<强> util.js中

/**
 * Created by admin on 22/12/14.
 */

var util = {
    scrollTo: function(id) {

        // This scrolling function
        // is from http://www.itnewb.com/tutorial/Creating-the-Smooth-Scroll-Effect-with-JavaScript

        var startY = currentYPosition();
        var stopY = elmYPosition(id);
        var distance = stopY > startY ? stopY - startY : startY - stopY;
        if (distance < 100) {
            scrollTo(0, stopY);
            return;
        }
        var speed = Math.round(distance / 100);
        if (speed >= 20) speed = 20;
        var step = Math.round(distance / 25);
        var leapY = stopY > startY ? startY + step : startY - step;
        var timer = 0;
        if (stopY > startY) {
            for (var i = startY; i < stopY; i += step) {
                setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
                leapY += step;
                if (leapY > stopY) leapY = stopY;
                timer++;
            }
            return;
        }
        for (var i = startY; i > stopY; i -= step) {
            setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
            leapY -= step;
            if (leapY < stopY) leapY = stopY;
            timer++;
        }

        function currentYPosition() {
            // Firefox, Chrome, Opera, Safari
            if (self.pageYOffset) return self.pageYOffset;
            // Internet Explorer 6 - standards mode
            if (document.documentElement && document.documentElement.scrollTop)
                return document.documentElement.scrollTop;
            // Internet Explorer 6, 7 and 8
            if (document.body.scrollTop) return document.body.scrollTop;
            return 0;
        }

        function elmYPosition(id) {
            var elm = document.getElementById(id);
            var y = elm.offsetTop;
            var node = elm;
            while (node.offsetParent && node.offsetParent != document.body) {
                node = node.offsetParent;
                y += node.offsetTop;
            }
            return y;
        }
    },
    isNull: function (o) {
        return angular.isUndefined(o) || o === null || o === '';
    }
}

<强> about.html

<li><a ng-class="{active:isActive('about')}" ng-click="moveTo('about')">About</a></li>
<li><a ng-class="{active:isActive('keraleeyam')}" ng-click="moveTo('keraleeyam')">Keraleeyam Ayurveda</a></li>
<li><a ng-class="{active:isActive('management')}" ng-click="moveTo('management')">Management</a></li>
<li><a ng-class="{active:isActive('treatment')}" ng-click="moveTo('treatment')">Panchakarma Treatment</a></li>

而且,它对我有用:)。我还对实时网址进行了更改,以便您可以查看它。

注意:我仍在等待使用$anchorScroll方法的解决方案。如果你找到了我错过的任何东西,请帮助我。