Générer du contenu à l'aide d'Ajax - le défilement jusqu'à Id ne fonctionne pas
P粉208469050
P粉208469050 2024-04-04 09:29:39
0
1
586

Je génère du contenu de page basé sur des données obtenues via ajax. Le problème que j'ai est que lorsque je veux faire défiler jusqu'à un certain identifiant, le défilement ne se produit pas ou il défile vers le mauvais emplacement.

J'ai consulté les questions et réponses du SO mais je n'ai trouvé aucune bonne solution. Beaucoup de réponses concernent Angular ou React, mais rien de vraiment solide pour Plain Js.

Par exemple, supposons que l'utilisateur clique sur un lien "À propos de nous -> Projet", "À propos de nous" est la page et que le projet est situé dans l'identifiant à la fin de la page, qui contient du contenu.

Le problème survient lorsque je clique sur des liens depuis différentes pages.

En supposant que nous sommes sur la page d'accueil, nous cliquons sur le lien vers la page À propos de nous, section Projets (id project). C'est à ce moment-là que le défilement ne fonctionne pas comme prévu. Si nous cliquons sur l'élément lié, lorsque nous accédons à la page À propos de nous, ce problème ne se produit pas.

Étant donné que les données de la page sont rendues en javascript, je ne peux pas utiliser d'écouteurs d'événements DOMContentLoadedload car ils se déclenchent avant que le contenu ne soit généré (je pense).

Ci-dessous ma solution qui n'a pas fonctionné. Il devrait vérifier si l'identifiant est dans la fenêtre, sinon il devrait défiler.

Je ne veux pas utiliser setTimeout car cela peut ne pas toujours fonctionner (vitesse Internet lente, plus de contenu (images), etc.)

Toute aide serait grandement appréciée.

function generate(data){
   // code

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

        const element = document.getElementById(id);
        document.addEventListener('DOMContentLoaded', function () {
            console.log("loaded");
            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)
        );
    }
}

Si je peux fournir d'autres données, veuillez me le faire savoir.

P粉208469050
P粉208469050

répondre à tous(1)
P粉978551081

Bien que ce ne soit pas la solution la plus élégante jusqu'à présent.

Si quelqu'un peut trouver un meilleur moyen, faites-le-moi savoir.

EDIT : légère modification du code pour éliminer le problème du défilement programmatique même après que l'utilisateur a fait défiler.

function generateContent(data){
   // code

    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);
        }
    }
}
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal