繁体   English   中英

如何将具有平滑 animation 的 scrollIntoView 转换为 Promise?

[英]How can I convert scrollIntoView with smooth animation to a Promise?

我必须平滑地scrollIntoView特定元素,然后执行某些操作。

例子

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

我知道它不能这样做,因为本机scrollIntoView不会返回 Promise。 但是,我如何实现这样的目标?

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

您可以使用原型,我认为这可以解决您的问题,而无需下载任何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!")); 

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

解决此问题的一种方法是使用“ 平滑滚动到视图中”(如果有),它实际上会返回一个承诺,因此您可以绑定到它并应用您的逻辑。

有一个想法可以捕捉动画结尾。 您可以在香草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);

我是这样弄的

const scrollIntoViewPromise = async (node: HTMLElement, options?: ScrollIntoViewOptions) => {
    node.scrollIntoView(options);

    return new Promise((resolve) => {
        const intersectionObserver = new IntersectionObserver((entries) => {
            const [entry] = entries;
            if (entry.isIntersecting) {
                setTimeout(() => {
                    resolve(true);
                    intersectionObserver.unobserve(node);
                }, 100);
            }
        });
        intersectionObserver.observe(node);
    });
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM