tutorial - ventana hija javascript
¿Hay una manera de detectar el desplazamiento horizontal solo sin desencadenar un reflujo del navegador? (7)
¿Qué hay de escuchar la entrada directamente?
element.addEventListener(''wheel'', e => {
if ( e.deltaX !== 0 ) {
horizontal();
}
if ( e.deltaY !== 0 ) {
vertical();
}
})
También es posible que necesites crear tus propias barras de desplazamiento y escuchar cómo arrastrarlas. Está reinventando la rueda (jajaja), pero bueno, no hay scrollTop
o scrollLeft
a la vista.
Puede detectar un evento de desplazamiento del navegador en un elemento arbitrario con:
element.addEventListener(''scroll'', function (event) {
// do something
});
Me gustaría poder diferenciar entre desplazamiento vertical y desplazamiento horizontal y ejecutar acciones para ellos de forma independiente.
Actualmente estoy haciendo esto escondiendo los valores de element.scrollTop y element.scrollLeft, y luego comparándolos dentro del detector de eventos. P.ej
var scrollLeft, scrollTop;
element.addEventListener(''scroll'', function (event) {
if (scrollLeft !== element.scrollLeft) {
// horizontally scrolled
scrollLeft = element.scrollLeft;
}
if (scrollTop !== element.scrollTop) {
// vertically scrolled
scrollTop = element.scrollTop;
}
});
Esto funciona bien, sin embargo, desde https://gist.github.com/paulirish/5d52fb081b3570c81e3a leí que leer los valores de scrollLeft o scrollTop provoca un reflujo.
¿Hay una mejor manera de hacer esto sin causar un reflujo del navegador en el desplazamiento?
Como se dijo en la respuesta de @Nelson, no hay forma de verificar entre desplazamiento horizontal y vertical, y la razón es que el objeto de evento activado tiene cero información sobre él (lo acabo de verificar).
Mozilla tiene un montón de ejemplos de cómo controlar la comprobación de propiedades del elemento, pero personalmente prefiero el enfoque setTimeout
, porque puede ajustar la respuesta del FPS para que se ajuste a sus necesidades. Con eso en mente, escribí este ejemplo de lectura a uso:
<html>
<head>
<meta charset="utf-8"/>
<style>
#foo {
display: inline-block;
width: 500px;
height: 500px;
overflow: auto;
}
#baz {
display: inline-block;
background: yellow;
width: 1000px;
height: 1000px;
}
</style>
</head>
<body>
<div id="foo">
<div id="baz"></div>
</div>
<script>
// Using ES5 syntax, with ES6 classes would be easier.
function WaitedScroll(elem, framesPerSecond, onHorz, onVert) {
this.isWaiting = false;
this.prevLeft = 0;
this.prevTop = 0;
var _this = this;
elem.addEventListener(''scroll'', function() {
if (!_this.isWaiting) {
_this.isWaiting = true;
setTimeout(function() {
_this.isWaiting = false;
var curLeft = elem.scrollLeft;
if (_this.prevLeft !== curLeft) {
_this.prevLeft = curLeft;
if (onHorz) onHorz();
}
var curTop = elem.scrollTop;
if (_this.prevTop !== curTop) {
_this.prevTop = curTop;
if (onVert) onVert();
}
}, 1000 / framesPerSecond);
}
});
}
// Usage with your callbacks:
var waiter = new WaitedScroll(
document.getElementById(''foo''), // target object to watch
15, // frames per second response
function() { // horizontal scroll callback
console.log(''horz'');
},
function() { // vertical scroll callback
console.log(''veeeeeeeertical'');
}
);
</script>
</body>
</html>
Creo que su código es correcto, porque al final del día necesita leer una de esas propiedades para averiguar la dirección de desplazamiento, pero la clave aquí para evitar problemas de rendimiento es acelerar el evento , porque de lo contrario se scroll
evento de scroll
con demasiada frecuencia y esa es la causa raíz de los problemas de rendimiento.
Entonces, su código de ejemplo adaptado para estrangular el evento de scroll
sería así:
var ticking = false;
var lastScrollLeft = 0;
$(window).scroll(function() {
if (!ticking) {
window.requestAnimationFrame(function() {
var documentScrollLeft = $(document).scrollLeft();
if (lastScrollLeft != documentScrollLeft) {
console.log(''scroll x'');
lastScrollLeft = documentScrollLeft;
}
ticking = false;
});
ticking = true;
}
});
Fuente: https://developer.mozilla.org/en-US/docs/Web/Events/scroll#Example
Elementos que utilizan la position: absolute;
Se sacan del flujo de documentos (ver fuente) .
Con esto en mente, puedes usar CSS para hacer que tu element
esté absolutamente posicionado dentro de su elemento primario ...
#parent{
width: 500px;
height: 100px;
// ...or whatever dimensions you need the scroll area to be
position: relative;
}
#element{
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
}
... y luego puede sentirse libre de leer los element.scrollLeft
y element.scrollTop
como lo hizo en su pregunta original sin temor a que los cuellos de botella vuelvan a afectar a todo el DOM.
Este enfoque también se recomienda en las directrices para desarrolladores de Google .
Espero que en realidad no ...
Pero de acuerdo a ¿Cómo detectar el desplazamiento horizontal en jQuery? puede intentar:
var lastScrollLeft = 0;
$(window).scroll(function() {
var documentScrollLeft = $(document).scrollLeft();
if (lastScrollLeft != documentScrollLeft) {
console.log(''scroll x'');
lastScrollLeft = documentScrollLeft;
}
});
Necesidad de cronometrarlo para volver a verificar qué método es el más rápido ...
Prueba fast-dom biblioteca de fast-dom :
Ejecute el código de ejemplo en su lado localmente para obtener los datos de perfiles correctos.
import fastdom from ''fastdom''
let scrollLeft
let scrollTop
const fast = document.getElementById(`fast-dom`)
fast.addEventListener(`scroll`, function fastDom() {
fastdom.measure(() => {
if (scrollLeft !== fast.scrollLeft) {
scrollLeft = fast.scrollLeft
console.log(scrollLeft)
}
if (scrollTop !== fast.scrollTop) {
scrollTop = fast.scrollTop
console.log(scrollTop)
}
})
})
Puedes usar Intersection Observer API
Hay un polyfill w3c disponible ya que el soporte nativo no está lo suficientemente extendido.
El polyfill anuncia eventos de scroll.