detectar - javascript scroll div
Sincronizar div barra de desplazamiento a div no desplazado (4)
Cachear selectores ayudará.
Cambiando :
$(''.center-wrapper'').scroll(function(e) {
$(''.sidebar'').css({marginTop: -1 * $(this).scrollTop()});
$(''.topbar'').css({marginLeft: -1 * $(this).scrollLeft()});
});
A :
var _scroller = $(''.center-wrapper''),
_swrapper = $(''.sidebar-wrapper''),
_twrapper = $(''.topbar-wrapper'');
_scroller.scroll(function (e) {
_swrapper.scrollTop(_scroller.scrollTop());
_twrapper.scrollLeft(_scroller.scrollLeft());
});
.scroll()
trabajará muy duro si tiene que recrear los objetos jquery $(this)
cada vez.
Escribí esto en un comentario anoche, y aunque todavía no se ha podido realizar la prueba, en realidad sentí que esto debería agregarse como directamente relacionado con el rendimiento.
Podemos probarlo here
Más / los métodos - haciéndolos nativos también
También hay otras llamadas al método jquery que podemos cortar también. .scrollTop()
y .scrollLeft()
almacenando en caché y devolviendo el nativo _scrollernative = _scroller.get(0)
para hacer uso de las propiedades fácilmente disponibles scrollLeft
.
Me gusta :
var _scroller = $(''.center-wrapper''),
_scrollernative = _scroller.get(0),
_swrapper = $(''.sidebar-wrapper'').get(0),
_twrapper = $(''.topbar-wrapper'').get(0);
_scroller.scroll(function (e) {
_swrapper.scrollTop = _scrollernative.scrollTop;
_twrapper.scrollLeft = _scrollernative.scrollLeft;
});
Podemos probar esto here
Aprecio que su código pueda estar viendo más de uno de estos controles en la página, y es por eso que ha usado clases y necesita encontrar S(this)
lugar de usar ID.
Para eso seguiría usando los métodos de almacenamiento en caché anteriores, pero antes necesitamos crearlos uno por uno. (almacenamiento en caché antes de que iniciemos la función scroll () por instancia)
(function() {
var _scroller = $(''.center-wrapper''),
_swrapper = $(''.sidebar-wrapper'').get(0),
_twrapper = $(''.topbar-wrapper'').get(0);
function setScrollers(_thisscroller) {
_scrollernative = _thisscroller.get(0);
/* start the scroll listener per this event */
_thisscroller.scroll(function (e) {
_swrapper.scrollTop = _scrollernative.scrollTop;
_twrapper.scrollLeft = _scrollernative.scrollLeft;
});
}
_scroller.each(function() { setScrollers($(this)); });
})();
Podemos probar esto here
Pero como veo que .sidebar-wrapper y .topbar-wrapper son únicos, mabye .center-wrapper también es único.
Entonces, ¿qué tal si finalmente utilizamos los identificadores para estos elementos para acortar todo?
var _scroller = document.getElementById(''center-wrapper''),
_swrapper = document.getElementById(''sidebar-wrapper''),
_twrapper = document.getElementById(''topbar-wrapper'');
_scroller.onscroll = function() {
_swrapper.scrollTop = _scroller.scrollTop;
_twrapper.scrollLeft = _scroller.scrollLeft;
};
Podemos probar esto here
Tengo una página web con tres divs que se sincronizan juntos.
+----------+
| TOP |
+---+----------+
| | ||
| L | CENTER ||
| |_________||
+---+----------+
<!--Rough HTML-->
<div>
<div class="topbar-wrapper">
<div class="topbar"></div>
</div>
<div class="container">
<div class="sidebar-wrapper">
<div class="sidebar"></div>
</div>
<div class="center-wrapper"> <!-- Set to the window size & overflow:scroll -->
<div class="center"></div> <!-- Has the content -->
</div>
</div>
</div>
El div centro tiene barras de desplazamiento, tanto horizontales como verticales. Los divs superior e izquierdo no tienen barras de desplazamiento. En cambio, cuando se mueve la barra de desplazamiento horizontal, el evento de desplazamiento actualiza el margin-left
del div. margin-left
apropiada. Del mismo modo, cuando se mueve la barra de desplazamiento vertical, el margin-top
se actualiza. En ambos casos, se establecen en un valor negativo.
$(''.center-wrapper'').scroll(function(e) {
$(''.sidebar'').css({marginTop: -1 * $(this).scrollTop()});
$(''.topbar'').css({marginLeft: -1 * $(this).scrollLeft()});
});
Esto funciona bien en Chrome y Firefox. Pero en Safari, hay un retraso entre mover la barra de desplazamiento y el margen negativo correctamente configurado.
¿Hay una mejor manera de hacer esto? ¿O hay alguna manera de deshacerse del retraso en Safari?
EDITAR:
Echa un vistazo a este violín para ver el retraso en Safari: http://jsfiddle.net/qh2K3/
Déjame saber si este JSFiddle funciona mejor. También experimenté el mismo "retraso" en mi final (Safari 7 en OS X) y estos pequeños cambios de CSS lo mejoraron significativamente . Mi mejor conjetura es que Safari está siendo perezoso y no ha encendido sus motores de alto rendimiento. Podemos forzar a Safari a que lo active utilizando algunos CSS simples:
.topbar-wrapper, .sidebar-wrapper, .center-wrapper {
-webkit-transform: translateZ(0);
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
}
Esto permite el CSS acelerado por hardware en Safari al descargar parte del trabajo a la GPU. Mejora la representación en el navegador, lo que puede haber sido el problema en el retraso.
En lugar de usar marginTop & marginLeft
para cambiar los márgenes de .sidebar & .topbar
use scrollTop & scrollLeft
para los divs desbordantes .sidebar-wrapper & .topbar-wrapper
y vea si ahora funciona en Safari :
Demo Fiddle
$(''.center-wrapper'').scroll(function(e) {
$(''.sidebar-wrapper'').scrollTop($(this).scrollTop());
$(''.topbar-wrapper'').scrollLeft($(this).scrollLeft());
});
Prueba este violín hecho para verse mejor en safari y probado
He tenido este problema unas cuantas veces, donde el safari parece estar retrasado cuando se mueven incrementalmente elementos basados en eventos como este.
Así es como he resuelto el problema en el pasado.
En los navegadores que admiten la aceleración de hardware, el uso de cualquier propiedad CSS "3d" habilitará la compatibilidad de hardware.
Si las transformaciones en 3D son compatibles, también podríamos usar translate3d para mover los elementos, ya que eso hace que los movimientos sean más suaves que cambiar los píxeles.
Esto significa que primero tenemos que encontrar el prefijo correcto para la propiedad de transformación de CSS y luego verificar el soporte para las transformaciones 3D. Si tenemos soporte, traducimos los elementos, si no cambiamos los píxeles.
Al calcular los prefijos y el soporte 3D sin bibliotecas, debería ser lo más rápido posible, y no tiene dependencias.
var parent = document.querySelector(''.center-wrapper''),
sidebar = document.querySelector(''.sidebar''),
topbar = document.querySelector(''.topbar''),
has3D = false,
transform = null,
transforms = {
''webkitTransform'' : ''-webkit-transform'',
''OTransform'' : ''-o-transform'',
''msTransform'' : ''-ms-transform'',
''MozTransform'' : ''-moz-transform'',
''transform'' : ''transform''
};
for (var k in transforms) if (k in parent.style) transform = k;
if ( transform !== null ) {
sidebar.style[transform] = ''translate3d(0,0,0)''; // start hardware acc
topbar.style[transform] = ''translate3d(0,0,0)''; // start hardware acc
// check support
var s = window.getComputedStyle(sidebar).getPropertyValue(transforms[transform]);
has3D = s !== undefined && s.length > 0 && s !== "none";
}
if (has3D) {
parent.onscroll = function (e) {
sidebar.style[transform] = ''translate3d(0px, ''+ (this.scrollTop * -1) +''px, 0px)'';
topbar.style[transform] = ''translate3d(''+ (this.scrollLeft * -1) +''px, 0px, 0px)'';
}
}else{
parent.onscroll = function (e) {
sidebar.style.marginTop = (this.scrollTop * -1) + ''px'';
topbar.style.marginLeft = (this.scrollLeft * -1) + ''px'';
}
}
Recuerde colocar esto después de los elementos en el DOM, como en justo antes </body>
, o si eso no es posible, tiene que estar envuelto en un controlador listo para DOM.
Como una nota al margen, querySelector no se admite en IE7 y más adelante, si ese es un problema, debe rellenarlo.