简体   繁体   中英

angularjs ui-router animated scroll to anchor

I have just found that I can navigate to anchor points using ui-router by setting up my links like this:

<ul>
    <li><a ui-sref="home({ '#': 'creative' })">creative</a></li>
    <li><a ui-sref="home({ '#': 'work' })">work</a></li>
    <li><a ui-sref="home({ '#': 'contact' })">contact</a></li>
</ul>

While this is great, I would like to animate to the anchor position. I figured I could use one of the state events, so I tried this:

$transitions.onFinish({ to: true }, function () {

    console.log('the state has changed');

    console.log($location.hash());
    var hash = $location.hash();

    if (hash) {
        var target = document.querySelector('#' + hash);

        console.log(target);

        var element = angular.element(target);

        console.log(element);

        $document.scrollToElement(element, 0, 2000);
    } else {

        // Scroll to the top of the page
        document.body.scrollTop = document.documentElement.scrollTop = 0;
    }
});

But the view hasn't loaded yet, so the element is not anywhere to find. If there a way of animating my scrollTo?

Main idea is to add this animation in proper moment. Proper moment will be when your view will be loaded and compiled. How can we be 100% sure that view is loaded and compiled? Add a directive to the view!

When view will be ready, directive will be initialized and you can bind your animation to the element. That is it.

Vitalii was right, creating a directive was the way to go. I simply did this:

angular.module('directives').directive('autoscroll', directive);

function directive($document, $location) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var offset = attrs.offset || 0;
            var duration = attrs.duration || 2000;              

            scope.$watch(function () {
                return $location.hash();
            }, function (hash) {
                if (hash) {
                    var anchor = document.querySelector('#' + hash);
                    var target = angular.element(anchor);
                    $document.scrollToElement(target, offset, duration);
                } else {
                    // Scroll to the top of the page if no hash has been supplied
                    document.body.scrollTop = document.documentElement.scrollTop = 0;
                }
            });
        }

    };
};

And used this on the actual view template file (with the target ids) and it worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM