【问题标题】:How to style focused and visited anchors when scrolling with CSS / jQuery使用 CSS / jQuery 滚动时如何设置焦点和访问锚的样式
【发布时间】:2014-10-31 21:22:08
【问题描述】:

我有一个相当复杂的问题,我自己似乎无法回答。

在我的页面顶部,我有几个可以平滑滚动到文章的锚点:

我想通过旋转箭头告诉访问者他们在页面上的位置。这个箭头应该指向它所代表的文章。在下一张图片中,您可以看到我想如何实现它。在这里,用户已经滚动过了锚点 1(这是一篇动态高度的文章),现在正在阅读锚点 2 的文章:

当访问者在文章之外,但锚点3文章仍在滚动位置下方时,应该是这样的:

这给我带来了一些问题:

  1. 是否可以编写 jQuery 脚本以便动态添加锚点?
  2. 如何在不添加额外库的情况下添加旋转动画? (我现在正在使用 jquery.transit )

当前代码:(从另一个帖子得到这个:jsfiddle.net/m2zQE)

 var topRange      = 200,  // measure from the top of the viewport to X pixels down
     edgeMargin    = 20,   // margin above the top or margin from the end of the page
     animationTime = 1200, // time in milliseconds
     contentTop = [];

$(document).ready(function(){ 

 // Stop animated scroll if the user does something
 $('html,body').bind('scroll mousedown DOMMouseScroll mousewheel keyup', function(e){
 if ( e.which > 0 || e.type == 'mousedown' || e.type == 'mousewheel' ){
  $('html,body').stop();
 }
})

 // Set up content an array of locations
 $('#navTopBar').find('a').each(function(){
  contentTop.push( $( $(this).attr('href') ).offset().top );
 })

 // Animate menu scroll to content
  $('#navTopBar').find('a').click(function(){
   var sel = this,
       newTop = Math.min( contentTop[ $('#navTopBar a').index( $(this) ) ], $(document).height() - $(window).height() ); // get content top or top position if at the document bottom
   $('html,body').stop().animate({ 'scrollTop' : newTop }, animationTime, function(){
    window.location.hash = $(sel).attr('href');
   });
   return false;
 })

 // rotate arrow
 $(window).scroll(function(){
  var winTop = $(window).scrollTop(),
      bodyHt = $(document).height(),
      vpHt = $(window).height() + edgeMargin;  // viewport height + margin
  $.each( contentTop, function(i,loc){
   if ( ( loc > winTop - edgeMargin && ( loc < winTop + topRange || ( winTop + vpHt ) >= bodyHt ) ) ){
    $('#navTopBar .anchor img')
     .removeClass('open')
     .eq(i).addClass('open');
   }
  })
 })

})

提前致谢!

【问题讨论】:

  • 你在哪里定义了edgeMargin?我想你被访问了:jsfiddle.net/m2zQE ?
  • 是的,完全正确。这与我试图实现的目标非常接近。

标签: jquery css scroll anchor


【解决方案1】:

我觉得这段代码看起来很眼熟;)

尝试这样的事情 (demo)

CSS

li.selected a:after { content :' \2192' }
li.above a:after { content :' \2191' }
li.below a:after { content :' \2193' }

脚本

 var topRange = 200, // measure from the top of the viewport to X pixels down
     edgeMargin = 20, // margin above the top or margin from the end of the page
     animationTime = 1200, // time in milliseconds
     contentTop = [];

 $(document).ready(function () {
     var $menu = $('#sidemenu li'),
         updateArrows = function (sel) {
             var indx = $menu.filter('.selected').index();
             $menu
                 .filter(':lt(' + indx + ')').removeClass('below').addClass('above').end()
                 .filter(':gt(' + indx + ')').removeClass('above').addClass('below');
         };

     // Stop animated scroll if the user does something
     $('html,body').bind('scroll mousedown DOMMouseScroll mousewheel keyup', function (e) {
         if (e.which > 0 || e.type == 'mousedown' || e.type == 'mousewheel') {
             $('html,body').stop();
         }
     });

     // Set up content an array of locations
     $menu.find('a').each(function () {
         contentTop.push($($(this).attr('href')).offset().top);
     });

     // Animate menu scroll to content
     $menu.find('a').click(function () {
         var sel = this,
             newTop = Math.min(contentTop[$('#sidemenu a').index($(this))], $(document).height() - $(window).height()); // get content top or top position if at the document bottom
         $('html,body').stop().animate({
             'scrollTop': newTop
         }, animationTime, function () {
             window.location.hash = $(sel).attr('href');
             updateArrows();
         });
         return false;
     });

     // adjust side menu
     $(window).scroll(function () {
         var sel,
         winTop = $(window).scrollTop(),
             bodyHt = $(document).height(),
             vpHt = $(window).height() + edgeMargin; // viewport height + margin
         $.each(contentTop, function (i, loc) {
             if ((loc > winTop - edgeMargin && (loc < winTop + topRange || (winTop + vpHt) >= bodyHt))) {
                 $menu.removeClass('selected')
                     .eq(i).removeClass('above below').addClass('selected');
             } else {
                 updateArrows();
             }
         });
     });

     updateArrows();

 });

如果你有兴趣,我实际上把这段代码变成了一个名为visualNav 的插件;它不包括这些更改 - 将类添加到所选链接的上方和下方,但在回调函数中添加应该相对容易。

【讨论】:

  • 感谢代码 Mottie!看起来真棒!快速问题:滚动通过锚点时如何添加类/删除类?这样它可以在 2 个类之间切换。它具有正常状态(未应用类,位于视口下方的锚点)、聚焦状态(已选择应用类 1、带有视口的锚点)和已访问状态(上方位于视口下方)。谢谢!
  • 我已经更新了我的答案,箭头会在 滚动时更新。您应该能够弄清楚如何根据需要调整类名;)
  • 效果很好!谢谢您的帮助!我注意到一些性能问题,你呢?干杯!
  • 是的,存在性能问题,因为箭头在 滚动时正在更新。我发布的原始版本仅在滚动停止后更新箭头。
猜你喜欢
  • 2010-10-13
  • 1970-01-01
  • 2023-03-07
  • 2011-09-04
  • 1970-01-01
  • 2014-12-08
  • 2019-05-15
  • 1970-01-01
  • 2011-11-23
相关资源
最近更新 更多