【问题标题】:jQuery position().top behaving the same as offset().top inside fixed parentjQuery position().top 的行为与固定父级中的 offset().top 相同
【发布时间】:2017-07-15 12:42:48
【问题描述】:

我试图制作一个位置感知滚动条,它使用固定 div 的顶部值而不是窗口。

jQuery 文档对 .position() 函数的描述如下,

.position() 方法允许我们检索元素(特别是其边距框)相对于偏移父级的当前位置

.offset() 方法描述如下

获取第一个元素的当前坐标,或设置匹配元素集中每个元素相对于文档的坐标。

我在这里收集的是.position() 应该是相对于父级,而offset() 总是相对于文档。

我正在尝试使我的菜单按钮相对于固定 div 中的当前滚动位置突出显示,而不是窗口。但是我从.position().top 得到的东西似乎永远不会与固定 div 的.scrollTop() 匹配

这是我的问题所在。如果我将事情切换到相对于窗口工作,一切都会很好。

第二次我尝试使它与父 div 相关,然后它就乱套了。

https://jsfiddle.net/cs83083/0kb5tm41/6/

对于小提琴不利,这里是代码!

感谢任何见解!

HTML

<div class="wrapper">
  <div class="menu-left">
    <div class="menu-item" data-target="sec1">
      Section 1
    </div>
    <div class="menu-item" data-target="sec2">
      Section 2
    </div>
    <div class="menu-item" data-target="sec3">
      Section 3
    </div>
    <div class="menu-item" data-target="sec4">
      Section 4
    </div>
  </div>

  <div class="page-content">
    <h2 class="header" id="sec1">Section 1</h2>
    <div class="text-block">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do 
        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 
        enim ad minim veniam, quis nostrud exercitation ullamco laboris 
        nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor

    </div>

    <h2 class="header" id="sec2">Section 2</h2>
    <div class="text-block">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do 
        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 
        enim ad minim veniam, quis nostrud exercitation ullamco laboris 
        nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor

    </div>

    <h2 class="header" id="sec3">Section 3</h2>
    <div class="text-block">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do 
        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 
        enim ad minim veniam, quis nostrud exercitation ullamco laboris 
        nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor

    </div>

    <h2 class="header" id="sec4">Section 4</h2>
    <div class="text-block">

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do 
        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 
        enim ad minim veniam, quis nostrud exercitation ullamco laboris 
        nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    </div>
   </div>
 </div>

CSS

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

.wrapper {
  padding-left: 240px;
  display: block;
}

.menu-left {
  background-color: #CCC !important;
  height: 100%;
  display: block;
  width: 240px;
  margin-left: -240px;
  position: fixed;
  z-index: 1000;
}

.page-content {
  background-color: #666;
  height: 100%;
  width: 100%;
  position: fixed;
  padding: 10px;
  overflow: scroll;
}

.menu-item {
  border-bottom: 1px solid #000;
  padding: 10px;
}

.menu-item:first-child {
  border-top: 1px solid #000;
}

.text-block {
  border: 1px solid #000;
  width: 600px;
  display: block;
  padding: 10px;
}

.menu-item:hover,
.active {
  background: #666;
  color: #fff;
}

JavaScript

container = $(".page-content");

$(".menu-item").click(function(e) {
  data_target = $(e.target).attr("data-target");
  container.animate({
    scrollTop: $("#" + data_target).offset().top - container.offset().top + container.scrollTop()
  }, 2000);
});

$('.menu-item').on('click', function(event) {
  $('.menu-item').removeClass('active');
  $(this).addClass('active');
});

container.on('scroll', function() {
//$(window).on('scroll', function() {
  $('.header').each(function() {

    if(container.scrollTop()  >= $(this).offset().top) {
    //if(container.scrollTop()  >= $(this).position().top) {
    //if ($(window).scrollTop() >= $(this).offset().top) {
      var id = $(this).attr('id');
      $('.menu-item').removeClass('active');
      $('div[data-target=' + id + ']').addClass('active');
    }
  });
});

【问题讨论】:

  • 问题是 container.scrollTop()$(this).offset().top 在滚动时会不断变化,因此您需要以某种方式存储每个标题的原始 offset().top 以便针对 container.scrollTop 进行测试

标签: javascript jquery html css


【解决方案1】:

看起来你最大的问题是你在 .on('scroll') 和容器 scrollTop() 中获得了标题的偏移量。这意味着每次滚动时它们都会“刷新”。您需要在文档加载时存储初始偏移量,然后运行滚动。

另外,由于您已经根据 scrollTop 设置了 addClass/removeClass,因此您在“单击”时无需再次添加它。这可能就是你行为不稳定的原因。

Here is the pen I drafted up

var headerIds = [];
var headerOffset = [];

$('.header').each(function(){
  headerIds.push(this.id)
  headerOffset.push($(this).offset().top)
})

$(".menu-item").click(function(e) {
  data_target = $(e.target).attr("data-target");
  container.animate({
    scrollTop: $("#" + data_target).offset().top - container.offset().top + container.scrollTop() 
  }, 2000);
});

$(container).on("scroll", function(e) {
  headerIds.forEach(function(el, i){
    if ($(container).scrollTop() > (headerOffset[i]-20)) {
      $('.menu-item').removeClass('active');
      $('.menu-item:nth-of-type(' + (i + 1) + ')').addClass('active');
      var id = $(this).attr('id');
    }
  });
});

【讨论】:

    猜你喜欢
    • 2014-02-23
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    相关资源
    最近更新 更多