AngularJS - $ anchorScroll mượt mà / thời lượng


115

Đọc tài liệu AngularJS, tôi chưa tìm ra liệu $anchorScrollcó thể có tùy chọn thời lượng / nới lỏng để cuộn mượt các phần tử hay không.

Nó chỉ nói:

$location.hash('bottom');

// call $anchorScroll()
$anchorScroll();

Tôi không sử dụng jquery và không muốn; vẫn còn một cách thông minh nhưng đơn giản để tạo hoặc mở rộng $anchorScrollđể làm cho việc cuộn trơn tru hơn?

Câu trả lời:


155

Thật không may, điều này là không thể sử dụng $anchorScroll. Như bạn đã phát hiện ra $anchorScrollkhông có bất kỳ tùy chọn nào và không hoạt động với $ngAnimate. Để tạo hoạt ảnh cho cuộn, bạn cần sử dụng dịch vụ / nhà máy của riêng mình hoặc chỉ javascript thẳng.

Để tự học, tôi đã tổng hợp một ví dụ với dịch vụ cuộn mượt mà. Có lẽ có nhiều cách tốt hơn để làm điều này nên mọi phản hồi đều được khuyến khích.

Để cuộn đến một phần tử, bạn đính kèm một ng-click="gotoElement(ID)"phần tử bất kỳ. Tôi nghĩ rằng một lộ trình tốt hơn sẽ là biến điều này thành một chỉ thị.

Đây là ví dụ làm việc trên jsFiddle .

Cập nhật

Hiện có một số chỉ thị của bên thứ ba để thực hiện việc này.


11
Rất đẹp. Đây là một chỉ thị: gist.github.com/justinmc/d72f38339e0c654437a2
Justin McCandless

@JustinMcBạn làm cách nào để gọi chỉ thị của mình? Tôi đã thử: <a ng-click="anchor-smooth-school('about');"> Khoảng 1 </a> <a ng-click="anchorSmoothScroll('about');"> Khoảng 2 < / a>
Dan

1
@Dan just do<a anchor-smooth-scroll>About 1</a> <a anchor-smooth-scroll>About 2</a>
Justin McCandless

1
Tốt, tôi thích câu trả lời này. Nhưng điều này vẫn thêm một lý do khác để ghét AngularJS, ý tôi là, hãy nhìn vào kích thước của cái này so với JQuery scrollTo
Felype

1
Để sử dụng các chỉ thị, tạo ra một yếu tố có ID (ví dụ <div id="my-div">my div</div>) và sau đó tạo ra một liên kết như thế này: <a anchor-smooth-scroll="my-div">visit my div</a>.
Jason Swett

20

Bạn cũng có thể sử dụng liên kết góc cuộn, " https://github.com/d bão hòa/angular-scroll / ". Nó là cuộn mượt mà cũng có một số chức năng nới lỏng để có được một cái nhìn chuyên nghiệp.


1
Plugin này có hoạt động trên các phần tử khác ngoài $ tài liệu không? Tôi cố gắng để áp dụng scrollToElement đến một div vì vậy tôi có thể di chuyển một hàng bên trong nó vào xem, và nó đã không làm việc ..
Shaunak

10

Câu trả lời từ Brett rất hiệu quả đối với tôi. Tôi đã thực hiện một số thay đổi nhỏ về giải pháp của anh ấy về mặt mô-đun hóa và khả năng kiểm tra.

Đây là một ví dụ hoạt động khác trên JsFiddle bao gồm phiên bản khác có bao gồm thử nghiệm.

Để thử nghiệm, tôi đang sử dụng Karma và Jasmine. Chữ ký đã được sửa đổi một chút như sau:

 anchorSmoothScroll.scrollTo(elementId, speed);

Trong đó phần tử là thuộc tính bắt buộc phải cuộn đến và tốc độ là tùy chọn trong đó giá trị mặc định là 20 (như trước đây).



2

Không có giải pháp nào ở đây thực sự làm được những gì OP yêu cầu ban đầu, đó là làm cho việc $anchorScrollcuộn trơn tru. Sự khác biệt giữa chỉ thị cuộn trơn và $anchroScrollnó sử dụng / sửa đổi $location.hash(), điều này có thể mong muốn trong một số trường hợp.

Đây là ý chính cho mô-đun đơn giản thay thế cuộn $ anchorScroll bằng cuộn trơn. Nó sử dụng https://github.com/oblador/angular-scroll thư viện để cuộn (thay thế nó bằng thứ khác nếu bạn muốn, nó sẽ dễ dàng).

https://gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
Lưu ý: Nó thực sự không nhận được $ anchorScroll để cuộn trơn tru, nhưng nó thay thế trình xử lý của nó để cuộn.

Kích hoạt nó đơn giản bằng cách tham chiếu mdvorakSmoothScrollmô-đun trong ứng dụng của bạn.


0

Alan, cảm ơn bạn. Nếu ai quan tâm, tôi đã định dạng nó dựa trên các tiêu chuẩn của John Pappa.

(function() {

'use strict';
var moduleId = 'common';
var serviceId = 'anchorSmoothScroll';

angular
    .module(moduleId)
    .service(serviceId, anchorSmoothScroll);

anchorSmoothScroll.$inject = ['$document', '$window'];

function anchorSmoothScroll($document, $window) {

    var document = $document[0];
    var window = $window;

    var service = {
        scrollDown: scrollDown,
        scrollUp: scrollUp,
        scrollTo: scrollTo,
        scrollToTop: scrollToTop
    };
    return service;

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

    function getElementY(doc, element) {
        var y = element.offsetTop;
        var node = element;
        while (node.offsetParent && node.offsetParent !== doc.body) {
            node = node.offsetParent;
            y += node.offsetTop;
        }
        return y;
    }

    function scrollDown(startY, stopY, speed, distance) {

        var timer = 0;

        var step = Math.round(distance / 25);
        var leapY = startY + step;

        for (var i = startY; i < stopY; i += step) {
            setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed);
            leapY += step;
            if (leapY > stopY) leapY = stopY;
            timer++;
        }
    };

    function scrollUp(startY, stopY, speed, distance) {

        var timer = 0;

        var step = Math.round(distance / 25);
        var leapY = startY - step;

        for (var i = startY; i > stopY; i -= step) {
            setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed);
            leapY -= step;
            if (leapY < stopY) leapY = stopY;
            timer++;
        }
    };

    function scrollToTop(stopY) {
        scrollTo(0, stopY);
    };

    function scrollTo(elementId, speed) {

        var element = document.getElementById(elementId);

        if (element) {
            var startY = getCurrentPagePosition(window, document);
            var stopY = getElementY(document, element);

            var distance = stopY > startY ? stopY - startY : startY - stopY;

            if (distance < 100) {
                this.scrollToTop(stopY);

            } else {

                var defaultSpeed = Math.round(distance / 100);
                speed = speed || (defaultSpeed > 20 ? 20 : defaultSpeed);

                if (stopY > startY) {
                    this.scrollDown(startY, stopY, speed, distance);
                } else {
                    this.scrollUp(startY, stopY, speed, distance);
                }
            }

        }

    };

};

})();

0

Tôi không biết cách tạo hoạt ảnh $anchorScroll. Đây là cách tôi làm điều đó trong các dự án của mình:

/* Scroll to top on each ui-router state change */
$rootScope.$on('$stateChangeStart', function() {
 scrollToTop();
});

Và hàm JS:

function scrollToTop() {
    if (typeof jQuery == 'undefined') {
        return window.scrollTo(0,0);
    } else {
        var body = $('html, body');
        body.animate({scrollTop:0}, '600', 'swing');
    }
    log("scrollToTop");
    return true;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.