如何将带有平滑动画的scrollIntoView转换为Promise?

时间:2019-04-23 11:50:31

标签: javascript angular

我必须平稳地scrollIntoView某个特定元素,然后再做些事情。

示例

element.scrollIntoView({behavior: 'smooth'}).then(() => {
    // Do something here
})

我知道无法以这种方式完成,因为本地scrollIntoView不会返回Promise。但是,我如何实现这样的目标?

我正在使用Angular 7 BTW。因此,如果有任何指令可以帮助我实现这一目标,那就太好了。

3 个答案:

答案 0 :(得分:3)

您可以使用原型,我认为这可以解决您的问题,而无需下载任何npm软件包

/* Extends Element Objects with a function named scrollIntoViewPromise
*  options: the normal scrollIntoView options without any changes
*/

Element.prototype.scrollIntoViewPromise = function(options){

  // "this" refers to the current element (el.scrollIntoViewPromise(options): this = el)
  this.scrollIntoView(options);
  
  // I create a variable that can be read inside the returned object ({ then: f() }) to expose the current element 
  let parent = this;
  
  // I return an object with just a property inside called then
  // then contains a function which accept a function as parameter that will be execute when the scroll ends 
  return { 
    then: function(x){
      // Check out https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API for more informations  
      const intersectionObserver = new IntersectionObserver((entries) => {
        let [entry] = entries;
        
        // When the scroll ends (when our element is inside the screen)
        if (entry.isIntersecting) {
        
          // Execute the function into then parameter and stop observing the html element
          setTimeout(() => {x(); intersectionObserver.unobserve(parent)}, 100)
        }
      });
      
      // I start to observe the element where I scrolled 
      intersectionObserver.observe(parent);
    }
  };
}


element.scrollIntoViewPromise({behavior: "smooth"}).then(()=>console.log("EHI!"));

我已经创建了example。我知道这不是一个有角度的应用程序,但这是一个很好的起点。您只需要实现它即可(如果您使用的是Typescript,则必须创建一个使用新功能扩展Element的接口)。

答案 1 :(得分:1)

解决此问题的一种方法是使用smooth-scroll-into-view-if-nedded,它实际上会返回一个承诺,因此您可以绑定到它并应用您的逻辑。

答案 2 :(得分:1)

有一个想法,您可以如何捕捉动画结尾。 您可以在香草JS中使用“滚动”事件监听器进行操作。 检查此示例https://codepen.io/Floky87/pen/BEOYvN

var hiddenElement = document.getElementById("box");
var btn = document.querySelector(".btn");
var isScrolling;

function handleScroll(event) {
  // Clear our timeout throughout the scroll
  window.clearTimeout(isScrolling);

  // Set a timeout to run after scrolling ends
  isScrolling = setTimeout(function() {
    alert(1);
    document.removeEventListener("scroll", handleScroll);
  }, 66);
}

function handleButtonClick() {
  document.addEventListener("scroll", handleScroll, false);
  hiddenElement.scrollIntoView({ block: "center", behavior: "smooth" });
}

btn.addEventListener("click", handleButtonClick);