Comment puis-je savoir la direction de défilement du serveur D'intersection?

alors, comment puis-je savoir la direction de défilement quand l'événement est déclenché?

dans l'objet retourné, la possibilité la plus proche que je vois est d'interagir avec le boundingClientRect sorte de sauver la dernière position de défilement mais je ne sais pas si la manipulation boundingClientRect finir sur des problèmes de performances.

est-il possible d'utiliser l'événement d'intersection pour déterminer la direction du rouleau (haut / bas)?

j'ai ajouté cet extrait de base, donc si quelqu'un peut m'aider.

Je serai très reconnaissant.

Voici le bout de code:

var options = {
  rootMargin: '0px',
  threshold: 1.0
}

function callback(entries, observer) { 
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      console.log('entry', entry);
    }
  });
};

var elementToObserve = document.querySelector('#element');
var observer = new IntersectionObserver(callback, options);

observer.observe(elementToObserve);
#element {
  margin: 1500px auto;
  width: 150px;
  height: 150px;
  background: #ccc;
  color: white;
  font-family: sans-serif;
  font-weight: 100;
  font-size: 25px;
  text-align: center;
  line-height: 150px;
}
<div id="element">Observed</div>

je voudrais savoir ceci, donc je peux appliquer ceci sur le menu headers fixe pour l'afficher / le cacher

19
demandé sur Jose Paredes 2017-09-28 23:58:00

5 réponses

Je ne sais pas si la gestion de boundingClientRect se terminera sur des problèmes de performance.

MDN indique que le IntersectionObserver ne fonctionne pas sur le thread principal:

de cette façon, les sites n'ont plus besoin de faire quoi que ce soit sur le fil principal pour surveiller ce genre d'intersection d'éléments, et le navigateur est libre d'optimiser la gestion des intersections comme il l'entend.

MDN, "L'Observateur D'Intersection API"

nous pouvons calculer la direction de défilement en sauvegardant la valeur de IntersectionObserverEntry.boundingClientRect.y et comparez cela à la valeur précédente.

exécutez l'extrait suivant pour un exemple:

const state = document.querySelector('.observer__state')
const target = document.querySelector('.observer__target')

const thresholdArray = steps => Array(steps + 1)
 .fill(0)
 .map((_, index) => index / steps || 0)

let previousY = 0
let previousRatio = 0

const handleIntersect = entries => {
  entries.forEach(entry => {
    const currentY = entry.boundingClientRect.y
    const currentRatio = entry.intersectionRatio
    const isIntersecting = entry.isIntersecting

    // Scrolling down/up
    if (currentY < previousY) {
      if (currentRatio > previousRatio && isIntersecting) {
        state.textContent ="Scrolling down enter"
      } else {
        state.textContent ="Scrolling down leave"
      }
    } else if (currentY > previousY && isIntersecting) {
      if (currentRatio < previousRatio) {
        state.textContent ="Scrolling up leave"
      } else {
        state.textContent ="Scrolling up enter"
      }
    }

    previousY = currentY
    previousRatio = currentRatio
  })
}

const observer = new IntersectionObserver(handleIntersect, {
  threshold: thresholdArray(20),
})

observer.observe(target)
html,
body {
  margin: 0;
}

.observer__target {
  position: relative;
  width: 100%;
  height: 350px;
  margin: 1500px 0;
  background: rebeccapurple;
}

.observer__state {
  position: fixed;
  top: 1em;
  left: 1em;
  color: #111;
  font: 400 1.125em/1.5 sans-serif;
  background: #fff;
}
<div class="observer__target"></div>
<span class="observer__state"></span>

Si le thresholdArray la fonction helper pourrait vous embrouiller, elle construit un tableau allant de 0.01.0par le nombre de mesures. En passant 5 retour [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].

2
répondu Jason 2018-08-23 08:29:25

comparer boundingClientRect et rootBoundsentry, vous pouvez facilement savoir si la cible est au-dessus ou au-dessous du viewport.

pendant callback(), vous cochez isAbove / isBelow puis, à la fin, vous le stockez dans wasAbove/wasBelow. La prochaine fois, si la cible arrive dans viewport (par exemple), vous pouvez vérifier si elle était au-dessus ou en dessous. Donc tu sais si ça vient du haut ou du bas.

Vous pouvez essayer quelque chose comme ceci:

var wasAbove = false;

function callback(entries, observer) {
    entries.forEach(entry => {
        const isAbove = entry.boundingClientRect.y < entry.rootBounds.y;

        if (entry.isIntersecting) {
            if (wasAbove) {
                // Comes from top
            }
        }

        wasAbove = isAbove;
    });
}

J'espère que cela vous aidera.

5
répondu thierrymichel 2017-11-05 02:18:52

:)

Je ne pense pas que ce soit possible avec une seule valeur de seuil. Vous pourriez essayer de regarder pour le intersectionRatio qui, dans la plupart des cas, est quelque chose en dessous de 1 quand le container quitte le viewport (parce que l'observateur d'intersection tire async). Je suis presque sûr que ça pourrait être 1 trop cependant si le navigateur rattrape assez rapidement. (Je n'ai pas testé ce :D )

mais ce que vous pourriez peut-être faire est d'observer deux seuils en utilisant plusieurs valeurs. :)

threshold: [0.9, 1.0]

Si vous obtenez un événement pour l' 0.9 d'abord il est clair que le conteneur entre dans le viewport...

J'espère que cela vous aidera. :)

2
répondu stefan judis 2017-09-29 07:45:57

Mon exigence était:

  • ne rien faire sur scroll-up
  • sur faites défiler vers le bas, de décider si un élément a commencé à cacher l'écran de haut

j'ai besoin de voir quelques informations fournies par IntersectionObserverEntry:

  • intersectionRatio (qui devrait être à la baisse de 1.0)
  • lindingclientrect.bas
  • lindingclientrect.hauteur

alors le rappel a fini par ressembler à:

intersectionObserver = new IntersectionObserver(function(entries) {
  const entry = entries[0]; // observe one element
  const currentRatio = intersectionRatio;
  const newRatio = entry.intersectionRatio;
  const boundingClientRect = entry.boundingClientRect;
  const scrollingDown = currentRatio !== undefined && 
    newRatio < currentRatio &&
    boundingClientRect.bottom < boundingClientRect.height;

  intersectionRatio = newRatio;

  if (scrollingDown) {
    // it's scrolling down and observed image started to hide.
    // so do something...
  }

  console.log(entry);
}, { threshold: [0, 0.25, 0.5, 0.75, 1] });

Voir mon post pour les codes complets.

1
répondu bob 2017-11-28 21:58:38

De cette Comment puis-je déterminer la direction d'un événement jQuery scroll? ainsi que votre code , j'ai fait le code suivant , l'essayer :

var options = {
  rootMargin: '0px',
  threshold: 1.0
               }

function callback(entries, observer) { 
  entries.forEach(entry => {
    if (entry.isIntersecting) {
    
  var scroll =document.getElementById("scroll").value;   
  console.log(entry.target.innerHTML+"  i am going   "+scroll);    
        
      
    }
  });
};


 var elementToObserve = document.querySelector('#element');
  var observer = new IntersectionObserver(callback, options);
    observer.observe(elementToObserve);
      
var x = 0;
$(window).scroll(function(event){
   var y = $(this).scrollTop();
     if (y > x){
     $("#scroll").val("up");              
      } else {
    $("#scroll").val("down");    
    
       }
      x = y;
    });
#element {
  margin: 1500px auto;
  width: 150px;
  height: 150px;
  background: #ccc;
  color: white;
  font-family: sans-serif;
  font-weight: 100;
  font-size: 25px;
  text-align: center;
  line-height: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div id="element">Observed</div>
<input type=hidden id=scroll>
0
répondu Mohammed Elhag 2017-10-07 23:46:14