将 URL 滚动更改为锚点,然后在到达顶部时移除

Change URL on scroll to anchor and then remove when reach the top

I have found a great piece of code 允许在您滚动到页面上的锚点时更改菜单栏中的 URL。

代码如下:

 function isElementInViewport (el) {
      //special bonus for those using jQuery
      if (typeof jQuery === "function" && el instanceof jQuery) {
        el = el[0];
      }
      var rect = el.getBoundingClientRect();
      return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
        rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
      );
    }
    // click-to-scroll behavior
    $(".anchor").click(function (e) {
      e.preventDefault();
      var section = this.href;
      var sectionClean = section.substring(section.indexOf("#"));
      $("html, body").animate({
        scrollTop: $(sectionClean).offset().top
      }, 1000, function () {
        window.location.hash = sectionClean;
      });
    });
    // listen for the scroll event
    $(document).on("scroll", function() {
      console.log("onscroll event fired...");
      // check if the anchor elements are visible
      $(".anchor").each(function (idx, el) {
        if ( isElementInViewport(el) ) {
          // update the URL hash
          if (window.history.pushState) {
            var urlHash = "#" + $(el).attr("id");
            window.history.pushState(null, null, urlHash);
          }
        }
      });
    });

唯一的问题是该页面仅以普通的 URL 开头,例如 https://sample.com, and when you scroll down it changes to https://sample.com/#hash 但是当您 return到顶部。

如果锚点不在视口内或根本看不到锚点,我希望能够更改此代码以删除散列。

我尝试在 if isElementInViewport 之后添加一些其他语句,但到目前为止还没有任何效果。

感谢任何帮助!

添加此条件:

if ( $(window).scrollTop() == 0 ) {
    window.history.pushState(null, null, window.location.pathname);
} else {
    window.history.pushState(null, null, urlHash);
}

因此,如果您位于最顶部,哈希将被清除。希望这是您想要实现的目标。

编辑(添加了带有更改的完整脚本):

// Source: 
// whosebug.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
function isElementInViewport(el) {
    //special bonus for those using jQuery
    if (typeof jQuery === "function" && el instanceof jQuery) {
        el = el[0];
    }
    var rect = el.getBoundingClientRect();
    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
        rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
    );
}
// click-to-scroll behavior
$(".anchor").click(function (e) {
    e.preventDefault();
    var section = this.href;
    var sectionClean = section.substring(section.indexOf("#"));
    $("html, body").animate({
        scrollTop: $(sectionClean).offset().top
    }, 1000, function () {
        window.location.hash = sectionClean;
    });
});
// listen for the scroll event
$(document).on("scroll", function () {
    console.log("onscroll event fired...");
    // check if the anchor elements are visible
    $(".anchor").each(function (idx, el) {
        if (isElementInViewport(el)) {
            // update the URL hash
            if (window.history.pushState) {
                var urlHash = "#" + $(el).attr("id");
                if ($(window).scrollTop() == 0) {
                    window.history.pushState(null, null, window.location.pathname);
                } else {
                    window.history.pushState(null, null, urlHash);
                }
            }
        }
    });
});