2015-12-11 15 views
15

che sto cercando di realizzare ciò che è descritto in questa domanda Stack Overflow, senza jQuery dipendenza: stackoverflow.com/questions/18358816/sticky-sidebar-stick-to-bottom-when-scrolling-down-top-when-scrolling-upFree-Scrolling Sticky Sidebar Senza jQuery

ma non ho voglia di dirottare questa domanda.

Fondamentalmente, voglio che il contenuto della barra laterale sia scorrevole indipendentemente, ma fissato quando la finestra di visualizzazione raggiunge entrambe le estremità del contenuto della barra laterale sullo scorrimento.

Il mio ostacolo principale sembra non essere in grado di calcolare la variabile elementTop quando la barra laterale è posizionata in modo assoluto e tra la parte superiore e inferiore del contenitore che ho impostato per essere a tutta altezza.

codice completo qui sotto:

var StickySidebar = function(eventie) { 

var container, containerTop, containerHeight, // container 
element, elementTop, elementHeight, elStyle, // element 
viewportTop = -1, viewportHeight, documentTop, // viewport 
lastViewportTop, scrollingDown, top = false , bottom = false,// sticky vars 

scroll = window.requestAnimationFrame || 
     window.webkitRequestAnimationFrame || 
     window.mozRequestAnimationFrame || 
     window.msRequestAnimationFrame || 
     window.oRequestAnimationFrame || 
     function(callback){ window.setTimeout(callback, 1000/60); }, 

options = { 
    container : document.querySelector('.sidebar-container'), 
    element : document.querySelector('.sidebar'), 
    sidebarClass : 'sidebar', 
    bottomOffset : -15, 
    topOffset: 90, 
}, 

_updateValue = function() { 
    viewportHeight = window.innerHeight; 
}, 

_offset = function(obj) {  
    var ol = ot = 0; 
    if (obj.offsetParent) { 
     do { 
      ol += obj.offsetLeft; 
      ot += obj.offsetTop; 
     } while (obj = obj.offsetParent); 
    } 
    return { 
     left: ol, 
     top: ot 
    }; 
}, 


init = function(){ 
    if(options.element !== null) { 

     container = options.container; 
     containerTop = offset(container).top; 
     containerHeight = container.clientHeight; 

     element = options.element; 
     elementTop = offset(element).top; 
     elementHeight = options.element.clientHeight; 

     lastViewportTop = window.scrollY; 
     viewportHeight = window.innerHeight; 

     eventie.bind(document, "scroll", _loop); 
     eventie.bind(window, "resize", _updateValue); 

    } 
}, 

_loop = function() { 
    if (viewportTop == window.pageYOffset) { 
     scroll(_loop); 
     return false; 
    } else viewportTop = window.pageYOffset; 

    _updateValue(); 

    var viewportBottom, elementTooBig, topOffset; 

    elementTop = offset(element).top; 

    elementHeight = element.clientHeight; 
    containerHeight = container.clientHeight; 
    scrollingDown = viewportTop > lastViewportTop; 
    elementTooBig = elementHeight > viewportHeight; 

    console.log("elementTop : " + elementTop); 
    console.log("viewportTop : " + viewportTop); 

    if (scrollingDown) { 

     if (viewportTop + viewportHeight >= elementTop + elementHeight) { 
      element.setAttribute('style','position:fixed; bottom:30px;'); 
     } else { 
      element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); // issue 1 
    } 

    if (viewportTop + viewportHeight > containerTop + containerHeight) { 
     element.setAttribute('style','position:absolute; bottom:0;'); 
    } 

} else { 

    if (viewportTop < containerTop - 60) { 
     element.removeAttribute('style'); 
     return; 
    } 

    if (viewportTop <= elementTop) { 
     element.setAttribute('style','position:fixed; top:90px;'); 
    } else { 
     element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); 
     elementTop = viewportTop + elementTop; 
    } 

} 

lastViewportTop = viewportTop; 

}; 


return { 
    init: init 
}; 

}(eventie); 

Ho cercato di affrontare questo problema per un paio di settimane, ed è stato alla guida insano. Qualsiasi aiuto sarebbe molto apprezzato.

+0

Si può semplicemente usare css con 'position: fixed;' per risolvere questo. E puoi usare [responsive design] (https://developers.google.com/web/fundamentals/design-and-ui/responsive/fundamentals/?hl=en) per schermo piccolo. Quindi non è necessario JS. – mrCyborg

+0

Grazie per la risposta, ma non funzionerà. Non sto cercando di essere scortese, ma non penso che tu capisca pienamente la domanda. –

+1

Stai [traducendo questa risposta] (http://stackoverflow.com/a/25025478/) in puro JS? – approxiblue

risposta

5

Se si sta solo cercando di ottenere il risultato desiderato non necessariamente creando ciò stesso - beh, ci sono molte librerie JavaScript che lo forniscono.

Ad esempio, Stickyfill è in realtà un polyfill per position: sticky che è natively supported only in Firefox 41+ and Safari 8+. Ecco the demo con tutti i tipi di viscosità che puoi immaginare :)

P.S. A prima vista potresti notare qualcosa su jQuery, ma è puro JavaScript e aggiunge solo un'estensione jQuery.

+1

Questo polyfill sembra non aderire al fondo. – approxiblue

+0

@approxiblue No, in realtà ti permette di avere elementi che si attaccano in fondo –

+0

Quale esempio? Dice che non può nel [README] (https://github.com/wilddeer/stickyfill#what-it-doesnt). – approxiblue

Problemi correlati