VelocityJS在相对容器内滚动错误

时间:2017-08-15 16:47:36

标签: jquery css-position css-transforms velocity.js

Velocity正在我项目的一部分工作,但我遇到的问题在JSFiddle中可以重现(链接如下),我认为它可能与项目的GitHub上的问题#770有关。页。

(注意:我在下面有这个和其他文章的链接,但是不具备发布超过2个链接的声誉,所以我很抱歉不得不查看这些链接。)

我想知道是否有人可以:

  • 确认这是一个已知错误,
  • 查看此问题的修复方法,
  • 在我的实施中找到错误,或
  • 提供另一种解决方案。

我正在构建一个实现屏幕外推送菜单的网站,其中整个内容包装在相对DIV中,该DIV使用CSS变换向右推,以显示菜单。有几个级别的相对定位的DIV模仿我的站点标题的固定位置(必要时,它包裹在推送菜单DIV中)。

推送菜单改编自 Codrops Playground 文章(搜索"多级推送菜单"在Tympanus.net上)。该文章链接了一个演示。还有一个关于元素的虚假定位注释的链接,结合文章中的CSS变换(中途)。

我的开发网站上的菜单按预期工作。我从一些菜单项中实现了Velocity,向下滚动到内部页面部分,这也很好(从页面顶部滚动)。

然而,我还希望在页面顶部的固定位置侧边栏中使用Velocity滚动,以允许用户单击部分标题以自动滚动到该部分。 不幸的是,侧栏链接仅在页面滚动到最顶层时才起作用。从任何其他滚动位置开始,链接无法正常运行。

如果页面向下滚动,则单击任何链接仅向下滚动页面,即使click事件中请求的部分高于当前滚动位置。

在这个小提琴中最好看到这种行为: http://jsfiddle.net/Josefism/j4dLhssc/

基本网站结构

<div class="site-container">
  <div class="menu-pusher">
    <div class="scroller">
      <div class="scroller-inner">
        <div class="site-inner">
          <div class="content-sidebar-wrap">
            <main class="content">
              <article class="page">
                <div class="entry-content">
                  <div id="section-1" class="section-1">
                    <p>Spicy jalapeno bacon ipsum.</p>    
                    <p>Cupim aliqua culpa bacon.</p>    
                    <p>Aliqua irure qui chicken.</p>
                  </div><!-- End Section 1 -->

                  <div id="section-2" class="section-2">
                    <p>Spicy jalapeno bacon ipsum.</p>    
                    <p>Cupim aliqua culpa bacon.</p>    
                    <p>Aliqua irure qui chicken.</p>
                  </div><!-- End Section 2 -->

                  <div id="section-3" class="section-3">
                    <p>Spicy jalapeno bacon ipsum.</p>    
                    <p>Cupim aliqua culpa bacon.</p>    
                    <p>Aliqua irure qui chicken.</p>
                  </div><!-- End Section 3 -->

                  <div id="section-4" class="section-4">
                    <p>Spicy jalapeno bacon ipsum.</p>    
                    <p>Cupim aliqua culpa bacon.</p>    
                    <p>Aliqua irure qui chicken.</p>
                  </div><!-- End Section 4 -->

                </div><!-- End Entry Content -->
              </article>
            </main>
            <aside class="sidebar">
              <section class="widget">
                <div class="widget-wrap">
                  <div class="text-widget">
                    <ul class="sidebar-menu">
                      <li class="section-1-link">Section 1</li>
                      <li class="section-2-link">Section 2</li>
                      <li class="section-3-link">Section 3</li>
                      <li class="section-4-link">Section 4</li>
                    </ul>
                  </div><!-- End Text Widget -->
                </div><!-- End Widget Wrap -->
              </section>
            </aside>
          </div><!-- End Content Sidebar Wrap -->
        </div><!-- End Site Inner -->
      </div><!-- End Scroller Inner -->
    </div><!-- End Scroller -->
  </div><!-- End Menu Pusher -->
</div><!-- End Site Container -->

CSS (仅修改以适应JSFiddle再现的问题)

body {
  font-family: Helvetica;
  width: 95%;
  margin: 0 auto;
  color: white;
  background: red;
  height: 100%;
  overflow: hidden;
}

.site-container {
  position: relative;
  overflow: hidden;
  height: 100%;
  margin-top: 90px;
}

.menu-pusher {
  position: relative;
  left: 0;
  height: 100%;
}

.scroller {
  position: relative;
  overflow-y: scroll;
  height: 400px;
}

.scroller-inner {
  position: relative;
}

.site-inner {
  position: relative;
}

main {
  display: block;
}

.content {
  float: right;
}

.content-sidebar-wrap .content {
  width: 100%;
}

.sidebar {
  float: left;
  width: 100%;
  top: 0px;
  position: fixed;
  display: block;
}

.sidebar .widget {
  padding: 20px;
  display: block;
  background-color: #CCC;
  color: #FFF;
}

.sidebar-menu {
  text-align: center;
}

.sidebar-menu li {
  list-style-type: none;
  padding: 0 1%;
  cursor: pointer;
  display: inline-block;
}

.sidebar-menu li:hover,
.sidebar-menu li.hovered {
  color: green;
}

.page {
  display: block;
}

.section-1 {
  background-color: #ddd;
  color: #000;
  padding: 20px 20px 100px 20px;
}

.section-2 {
  background-color: #FFF;
  color: #000;
  padding: 20px 20px 100px 20px;
}

.section-3 {
  background-color: #AAA;
  color: #FFF;
  padding: 20px 20px 100px 20px;
}

.section-4 {
  background-color: #555;
  color: #FFF;
  padding: 20px 20px 100px 20px;
  margin-bottom: 100px;
}

jQuery Velocity Implementation (不包括菜单项中的Velocity实现,因为那些已经有效。)

$(document).ready(function(e) {

  // Add Velocity scrolling to the internal section sidebar links
  $(".section-1-link").on("click", function() {
    $("#section-1").velocity("stop", true).velocity("scroll", {
      container: $(".scroller"),
      duration: 1000,
      easing: "easeInOutSine",
      delay: 300,
      offset: 1
    });
  });
  $(".section-2-link").on("click", function() {
    $("#section-2").velocity("stop", true).velocity("scroll", {
      container: $(".scroller"),
      duration: 1000,
      easing: "easeInOutSine",
      delay: 300,
      offset: 1
    });
  });
  $(".section-3-link").on("click", function() {
    $("#section-3").velocity("stop", true).velocity("scroll", {
      container: $(".scroller"),
      duration: 1000,
      easing: "easeInOutSine",
      delay: 300,
      offset: 1
    });
  });
  $(".section-4-link").on("click", function() {
    $("#section-4").velocity("stop", true).velocity("scroll", {
      container: $(".scroller"),
      duration: 1000,
      easing: "easeInOutSine",
      delay: 300,
      offset: 1
    });
  });

  // Callback to section menu in primary sidebar to indicate scroll position
  $(".scroller").on("scroll", function() {
    var scrollerTop = $(".scroller").scrollTop();
    var section1TopDist = $("#section-1").offset().top;
    var section2TopDist = $("#section-2").offset().top;
    var section3TopDist = $("#section-3").offset().top;
    var section4TopDist = $("#section-4").offset().top;
    if (section4TopDist < 90) {
      $(".section-2-link, .section-3-link, .section-1-link").removeClass("hovered");
      $(".section-4-link").addClass("hovered");
    } else if (section3TopDist < 90) {
      $(".section-2-link, .section-1-link, .section-4-link").removeClass("hovered");
      $(".section-3-link").addClass("hovered");
    } else if (section2TopDist < 90) {
      $(".section-1-link, .section-3-link, .section-4-link").removeClass("hovered");
      $(".section-2-link").addClass("hovered");
    } else if (section1TopDist < 90) {
      $(".section-2-link, .section-3-link, .section-4-link").removeClass("hovered");
      $(".section-1-link").addClass("hovered");
    } else {
      $(".section-1-link, .section-2-link, .section-3-link, .section-4-link").removeClass("hovered");
    }
  });

});

1 个答案:

答案 0 :(得分:0)

好吧,经过一些测试和故障排除后,我发现了导致我问题的原因。如果使用Velocity.js的其他人在包含元素内滚动时遇到类似的问题,我在此处发布我的解决方案作为故障排除参考。

问题,如下面代码块中的注释所述,是&#34; scrollPositionCurrent&#34;被添加到新的滚动位置并丢弃返回的总数。从计算中删除它对我来说是诀窍,现在在包含元素内滚动按预期工作。

我已经在其他网站中使用了我修改过的Velocity.js文件来滚动整个页面而没有包含元素,并且它仍然可以正常工作。

下面的代码块来自几天前(2017年10月中旬)GitHub上当前版本的Velocity.js的第3171-3205行。

原始代码仍然存在于代码段中以供参考,但已被注释掉。

/* Scroll also uniquely takes an optional "container" option, which indicates the parent element that should be scrolled --
as opposed to the browser window itself. This is useful for scrolling toward an element that's inside an overflowing parent element. */
if (opts.container) {
    /* Ensure that either a jQuery object or a raw DOM element was passed in. */
    if (Type.isWrapped(opts.container) || Type.isNode(opts.container)) {
        console.log("GOT IT!");
        /* Extract the raw DOM element from the jQuery wrapper. */
        opts.container = opts.container[0] || opts.container;
        /* Note: Unlike other properties in Velocity, the browser's scroll position is never cached since it so frequently changes
         (due to the user's natural interaction with the page). */
        scrollPositionCurrent = opts.container["scroll" + scrollDirection]; /* GET */

        /* $.position() values are relative to the container's currently viewable area (without taking into account the container's true dimensions
         -- say, for example, if the container was not overflowing). Thus, the scroll end value is the sum of the child element's position *and*
         the scroll container's current scroll position. */
        /* scrollPositionEnd = (scrollPositionCurrent + $(element).position()[scrollDirection.toLowerCase()]) + scrollOffset; */ /* GET */
        /* CORRECTION - Applied by Josef Cook 
           Scroll position of element within a containing element was incorrect. Adding current scroll position blows out the total. 
           Had to remove current scroll position addition (commented out above) to make this work correctly. */
        scrollPositionEnd = ($(element).position()[scrollDirection.toLowerCase()]) + scrollOffset;
        /* If a value other than a jQuery object or a raw DOM element was passed in, default to null so that this option is ignored. */
    } else {
        opts.container = null;
    }
} else {
    /* If the window itself is being scrolled -- not a containing element -- perform a live scroll position lookup using
     the appropriate cached property names (which differ based on browser type). */
    scrollPositionCurrent = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + scrollDirection]]; /* GET */
    /* When scrolling the browser window, cache the alternate axis's current value since window.scrollTo() doesn't let us change only one value at a time. */
    scrollPositionCurrentAlternate = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + (scrollDirection === "Left" ? "Top" : "Left")]]; /* GET */

    /* Unlike $.position(), $.offset() values are relative to the browser window's true dimensions -- not merely its currently viewable area --
     and therefore end values do not need to be compounded onto current values. */
    scrollPositionEnd = $(element).offset()[scrollDirection.toLowerCase()] + scrollOffset; /* GET */
}