Функция ScrollTo в AngularJS
Я пытаюсь получить быстрый навигатор, чтобы работать правильно. Он плавает на боку. Когда они нажимают на ссылку, она приводит их к этому идентификатору на странице. Я следую за этим руководство от Treehouse.
Это то, что у меня есть для прокрутки:
$("#quickNav a").click(function(){
var quickNavId = $(this).attr("href");
$("html, body").animate({scrollTop: $(location).offset().top}, "slow");
return false;
});
Я изначально поместил его перед </body>. Но я, кажется, впадаю в состояние гонки, где это стреляло до того, как quickNav скомпилирован (у него есть ng-hide помещенный на него, не уверен, что это вызывает его - но это так в дом).
Если я запускаю этот кусок кода в консоли, то прокрутка работает, как ожидалось.
Я подумал, что было бы более эффективно переместить это в контроллер - или, скорее всего, в директиве. Но мне не везет с этим делом. как я могу получить этот блок кода для работы с AngularJS?
9 ответов:
вот простая директива, которая будет прокручиваться до элемента по щелчку:
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>для прокрутки до элемента с идентификатором.
Это лучшая директива, если вы хотите ее использовать:
вы можете перейти к любому элементу на странице:
.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 элемента .
для анимации определенного элемента внутри контейнера прокрутки (фиксированный 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"); }
угловое решение с использованием $anchorScroll http://www.benlesh.com/2013/02/angular-js-scrolling-to-element-by-id.html:
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
и если вы заботитесь о чистом решении javascript, вот один:
вызовите 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...) прокрутите до верхней анимации
спасибо Энди за пример, это было очень полезно. Я закончил реализацию немного другой стратегии, так как я разрабатываю одностраничный свиток и не хочу, чтобы Angular обновлялся при использовании URL-адреса hashbang. Я также хочу сохранить назад / вперед действие браузера.
вместо использования директивы и хэша, я использую $ scope.$ смотрите на $location.поиск и получение цели оттуда. Это дает хороший чистый якорь тег
<a ng-href="#/?scroll=myElement">My element</a>Я приковал код часов к объявлению моего модуля в приложении.Яш вот так:
.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-адресу непосредственно с другого маршрута, DOM не может быть загружен вовремя для $target jQuery.offset () вызов. Решение состоит в том, чтобы вложить этот код в наблюдатель $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
я использовал ответ Эндрю Джослина, который отлично работает, но вызвал угловое изменение маршрута, что создало для меня нервный свиток. Если вы хотите избежать изменения маршрута,
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; }); } } });
а как же угловое-свиток, он активно поддерживается и нет никакой зависимости от jQuery..
другое предложение. Одна директива с селектором.
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
очень четкий ответ, используя только ANGULARJS, никакой JQUERY не зависит
в вашем html где-то внизу
<back-top>some text</back-top>в вашем html где-то сверху
<div id="top"></div>в вашем js:
/** * @ngdoc directive * @name APP.directive:backTop <pre> <back-top></back-top> </pre> */ angular .module('APP') .directive('backTop', ['$location', '$anchorScroll' ,function($location, $anchorScroll) { return { restrict: 'E', replace: true, transclude: true, template: '<span class=\'btn btn-mute pull-right\'><i class=\'glyphicon glyphicon-chevron-up\'></i><ng-transclude></ng-transclude></span>', scope: { }, link: function(scope, element) { element.on('click', function(event) { $anchorScroll(['top']); }); } }; }]);
Comments