これは古い質問ですが、最近、Web サイトを AngularJS アプリとして書き直したときに偶然見つけました。Bootstrap Affix プラグイン (スクロール時のアクティブ クラスの更新を含む) も使用していましたが、探していたものとまったく同じように機能するプラグインが見つからなかったため、独自のディレクティブを作成しました。
実際に見てみましょう: http://bobbograph.com/#/api
注: ディレクティブに提供される値は上部オフセットです。
JavaScript:
https://github.com/robertmesserle/Bobbograph/blob/v3/www/js/site.js#L102
app.directive('rmAffix', function ($window) {
var body = document.body,
win = document.defaultView,
docElem = document.documentElement,
isBoxModel = (function () {
var box = document.createElement('div'),
isBoxModel;
box.style.paddingLeft = box.style.width = "1px";
body.appendChild(box);
isBoxModel = box.offsetWidth == 2;
body.removeChild(box);
return isBoxModel;
})();
function getTop (element) {
var box = element.getBoundingClientRect(),
clientTop = docElem.clientTop || body.clientTop || 0,
scrollTop = win.pageYOffset || isBoxModel && docElem.scrollTop || body.scrollTop;
return box.top + scrollTop - clientTop;
}
return function ($scope, $element, $attrs) {
var offset = $scope.$eval($attrs.rmAffix),
elemTop = getTop($element[0]),
$links = $element.find('li'),
linkTops = [];
angular.forEach($links, function ($link) {
var $a = angular.element($link).find('a'),
href = $a.attr('href').substr(1),
target = document.getElementById(href),
elemTop = getTop(target);
linkTops.push(elemTop);
$a.on('click', function (event) {
window.scrollTo(0, elemTop - offset);
event.preventDefault();
});
});
angular.element($window).on('scroll', function (event) {
var top = window.pageYOffset,
index;
if (top > elemTop - offset) $element.addClass('affix');
else $element.removeClass('affix');
//-- remove selected class from all links
$links.removeClass('active');
//-- find the closest element
for (index = 1; index < linkTops.length; index++) {
if (linkTops[index] - 100 > top) break;
}
angular.element($links[index - 1]).addClass('active');
});
};
});
HTML (ジェイド)
https://github.com/robertmesserle/Bobbograph/blob/v3/www/api.jade#L288
ul.nav.nav-stacked.nav-pills(rm-affix=70)
li.active: a( href="#basic" ) Basic Usage
li: a( href="#options" ) Options
li: a( href="#data" ) Data
li: a( href="#padding" ) Padding