使用Ajax生成内容 – 滚动到Id不起作用

huangapple go评论79阅读模式
英文:

Generate content with Ajax - scroll to Id doesn't work

问题

我根据您的要求为您提供翻译的部分:

"我根据通过Ajax获取的数据生成页面内容。我遇到的问题是,当我想要滚动到一个ID时,要么滚动不发生,要么滚动到错误的位置。

我已经在Stack Overflow的问答中寻找了答案,但我没有找到任何很好的解决方案。很多答案都是针对Angular或React的,但对于纯JavaScript没有什么可靠的解决方案。

举个例子,假设用户点击一个链接“关于我们->项目”,其中“关于我们”是页面,而“项目”是页面末尾带有一些内容的ID。

问题发生在我从不同页面点击链接时。

假设我们在主页上,然后点击关于我们页面的项目链接(ID为projects)。这时滚动不起作用,不像预期的那样工作。如果我们在关于我们页面上点击项目链接,这个问题就不会发生。

由于页面数据是用JavaScript渲染的,我不能使用事件监听器DOMContentLoaded或load,因为它们会在内容生成之前触发(我认为)。

以下是我的非工作解决方案。它应该检查ID是否在视口中,如果不在,则应该滚动。

我不想使用setTimeout,因为它可能不会始终起作用(因为网络较慢,内容较多(图像)等原因)。

非常感谢您的帮助。

function generate(data){
   // 代码

    let idx = 0 // 以防万一,以免出现无限循环
    if (window.location.href.indexOf("#") !== -1) {
        const id = window.location.href.split("#")[1];

        const element = document.getElementById(id);
        document.addEventListener('DOMContentLoaded', function () {
            console.log("已加载");
            if (element) {
                while (!isInViewport(id)) {
                    idx = idx + 1;
                    console.log(isInViewport(id))
                    scrollToElement(id);
                    if (idx === 10000){
                        break;
                    }
                };
            }
        });
    }
}

generateContent();

function scrollToElement(id) {
    const element = document.getElementById(id);
    if (element) {
        element.scrollIntoView({
            behavior: 'smooth'
        });
    }
}

function isInViewport(id) {
    const element = document.getElementById(id);
    if (element) {
        const rect = element.getBoundingClientRect();
        return (
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );
    }
}

如果我可以提供任何其他数据,请告诉我。"

英文:

I am generating the page content depending on the data I get via ajax.
The problem I am having, is that when I would like to scroll to an ID, the scroll either doesn't happen or it scrolls to the wrong position.

I've been looking at SO q&a, but I haven't found any good solutions. A lot of answers are for Angular or React, but nothing really solid for plain js.

As an example, lets say the user clicks a link About us -> Project, where about us is the page and projects is in id at the end of the page with some content.

The problem occurs when I click the link from a different page.

Lets say we are on the home page, an we click a link for the about us page, section projects (id projects). This is when the scroll doesn't work as it is supposed to. If we click on the link project, when we are on the about us page, this problem doesn't happen.

As the page data in being rendered with javascript, I can't use event listeners DOMContentLoaded or load, as they trigger before the content is being generated (I think).

Below is my non working solution. It is supposed to check if the id is in viewport, and if not, it should scroll.

I don't want to use setTimeout as it might not always work (slow internet, more content (images) etc.)

Any help would be much appreciated.


function generate(data){
   // code

    let idx = 0 //just in case, so we don&#39;t have an infinite loop
    if (window.location.href.indexOf(&quot;#&quot;) !== -1) {
        const id = window.location.href.split(&quot;#&quot;)[1];

        const element = document.getElementById(id);
        document.addEventListener(&#39;DOMContentLoaded&#39;, function () {
            console.log(&quot;loaded&quot;);
            if (element) {
                while (!isInViewport(id)) {
                    idx = idx + 1;
                    console.log(isInViewport(id))
                    scrollToElement(id);
                    if (idx === 10000){
                        break;
                    }
                };
            }
        });
    }
}

generateContent();


function scrollToElement(id) {
    const element = document.getElementById(id);
    if (element) {
        element.scrollIntoView({
            behavior: &#39;smooth&#39;
        });
    }
}

function isInViewport(id) {
    const element = document.getElementById(id);
    if (element) {
        const rect = element.getBoundingClientRect();
        return (
            rect.top &gt;= 0 &amp;&amp;
            rect.left &gt;= 0 &amp;&amp;
            rect.bottom &lt;= (window.innerHeight || document.documentElement.clientHeight) &amp;&amp;
            rect.right &lt;= (window.innerWidth || document.documentElement.clientWidth)
        );
    }
}

If I can provide any additional data, please let me know.

答案1

得分: 0

虽然这不是最优雅的解决方案,但目前它有效。

如果有人能找出更好的解决方法,请告诉我。

编辑:稍微修改了代码,解决了用户滚动后仍然出现编程滚动问题。

function generateContent(data){
   // 代码

    if (window.location.href.indexOf("#") !== -1) {
        const id = window.location.href.split("#")[1];
        const element = document.getElementById(id);
        if (element) {
            scrollToLoop(id);
        }
    }
}
generateContent();

let isUserScrolling = false;
window.addEventListener("wheel", function () {
    isUserScrolling = true;
});
window.addEventListener("touchmove", function () {
    isUserScrolling = true;
});
function scrollToLoop(id, scrl) {
    let scroll = scrl;
    const element = document.getElementById(id);

    if (element) {
        if (!isInViewport(id) && scroll && !isUserScrolling) {
            scrollToElement(id);
            setTimeout(() => {
                if (!isInViewport(id)) {
                    scrollToLoop(id, true);
                }
            }, 500);
        } else {
            setTimeout(() => {
                if (!isInViewport(id) && scroll && !isUserScrolling) {
                    scrollToLoop(id, true);
                }
            }, 500);
        }
    }
}
英文:

while it is not the most elegant solution it is working so far.

If anyone can figure out something better, please let me know.

Edit: Changed the code a little bit, removing the problem with programmatic scrolling even after user scrolls.

function generateContent(data){
   // code

    if (window.location.href.indexOf(&quot;#&quot;) !== -1) {
        const id = window.location.href.split(&quot;#&quot;)[1];
        const element = document.getElementById(id);
        if (element) {
            scrollToLoop(id);
        }
    }
}
generateContent();

let isUserScrolling = false;
window.addEventListener(&quot;wheel&quot;, function () {
    isUserScrolling = true;
});
window.addEventListener(&quot;touchmove&quot;, function () {
    isUserScrolling = true;
});
function scrollToLoop(id, scrl) {
    let scroll = scrl;
    const element = document.getElementById(id);

    if (element) {
        if (!isInViewport(id) &amp;&amp; scroll &amp;&amp; !isUserScrolling) {
            scrollToElement(id);
            setTimeout(() =&gt; {
                if (!isInViewport(id)) {
                    scrollToLoop(id, true);
                }
            }, 500);
        } else {
            setTimeout(() =&gt; {
                if (!isInViewport(id) &amp;&amp; scroll &amp;&amp; !isUserScrolling) {
                    scrollToLoop(id, true);
                }
            }, 500);
        }
    }
}

huangapple
  • 本文由 发表于 2023年7月7日 02:54:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631773.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定