2016-09-16 5 views
1

J'essaie de créer un effet de parallaxe par lequel un élément enfant positionné de façon absolue doit se déplacer à une vitesse plus lente que celle de son défilement.Effet de parallaxe - calcul du décalage de l'enfant par parent sur le défilement

L'enfant sera toujours la hauteur de 130% de la société mère, mais le parent peut être toute taille:

HTML:

<div class="parallax-window lg"> 
 
    <div class="parallax-image image-1"></div> 
 
    <div class="parallax-content">Hello World</div> 
 
</div> 
 

 
<div class="parallax-window"> 
 
    <div class="parallax-image image-2"></div> 
 
    <div class="parallax-content">Hello World</div> 
 
</div>

CSS:

.parallax-window { 
 
    min-height: 300px; 
 
    position: relative; 
 
    overflow: hidden; 
 
} 
 

 
.parallax-window.lg { 
 
    min-height: 600px; 
 
} 
 

 
.parallax-image { 
 
    position: absolute; 
 
    top: 0; 
 
    left: 0; 
 
    width: 100%; 
 
    height: 130%; 
 
    background-size: cover; 
 
    background-repeat: no-repeat; 
 
    background-position: 50% 50%; 
 
    transform: translate3d(0, 0, 0); 
 
    z-index: -1; 
 
} 
 

 
.image-1 { 
 
    background-image: url(https://i.ytimg.com/vi/TbC-vUPMR7k/maxresdefault.jpg); 
 
} 
 

 
.image-2 { 
 
    background-image: url(https://i.ytimg.com/vi/xi5-YrAEChc/maxresdefault.jpg); 
 
}

J'ai une formule pour déplacer l'image, mais mes mathématiques est clairement loin:

var win = $(window), 
 
     win_h = win.height(), 
 
     parallaxers = $('.parallax-window'); 
 

 
    function scroll_events() { 
 
     var win_top = win.scrollTop(), 
 
      win_btm = win_top + win_h; 
 
    
 
     parallaxers.each(function() { 
 
      var cont = $(this), 
 
       cont_top = cont.offset().top, 
 
       cont_h = cont.height(), 
 
       cont_btm = cont_top + cont_h, 
 
       para = cont.find('.parallax-image'), 
 
       para_h = Math.round(cont_h * 1.3); 
 
      if (cont_btm > win_top && cont_top <= win_btm) { 
 
       var diff = (win_h - cont_h)/(win_h - para_h), 
 
        value = -Math.round((win_top * diff)); 
 
       // para.css('transform', 'translate3d(0,' + value*-1 + 'px, 0)'); 
 
       para.css('top', value + 'px'); 
 
      } 
 
     }); 
 
    }

Les images se déplacent, mais pas au bon taux.

L'image doit être alignée avec le haut du parent lorsque l'élément arrive pour la première fois dans la fenêtre. Ensuite, après le défilement, le bas de l'image doit être aligné avec le bas du parent lorsqu'il atteint le haut de la fenêtre.

Toute aide serait grandement appréciée!

VIOLON (https://jsfiddle.net/8dwLwgy7/1/)

Répondre

0

je me suis dit cela. Pour toute personne qui trébucherait à ce sujet dans le futur - l'astuce consistait à remplacer la valeur défilée de la fenêtre par le reste de la fenêtre défilant moins le haut de décalage de l'élément, moins la hauteur de l'élément.

calculer alors la vitesse en divisant la différence entre la hauteur du récipient et la hauteur de l'élément avec la plus grande soit de la fenêtre et le conteneur:

// Wrong: 
// value = -Math.round((win_top * diff)); 

// Right: 
var diff = elem_h - cont_h, 
    max = Math.max(cont_h, win_h), 
    speed = diff/max, 
    cont_scrolled = win_top - cont_top - cont_h, 
    value = Math.round(cont_scrolled * speed); 

para.css('top', value + 'px'); 

code de travail complet:

(function() { 
 
    var lastTime = 0; 
 
    var vendors = ['ms', 'moz', 'webkit', 'o']; 
 
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 
 
    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; 
 
    window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']; 
 
    } 
 
    if (!window.requestAnimationFrame) 
 
    window.requestAnimationFrame = function(callback, element) { 
 
     var currTime = new Date().getTime(); 
 
     var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 
 
     var id = window.setTimeout(function() { 
 
      callback(currTime + timeToCall); 
 
     }, 
 
     timeToCall); 
 
     lastTime = currTime + timeToCall; 
 
     return id; 
 
    }; 
 
    if (!window.cancelAnimationFrame) 
 
    window.cancelAnimationFrame = function(id) { 
 
     clearTimeout(id); 
 
    }; 
 
}()); 
 

 

 
(function($) { 
 

 
    var win = $(window), 
 
    win_h = win.height(); 
 
\t \t parallaxers = $('.parallax-window'), 
 
\t \t parallax_objs = [], 
 
    scroll_busy = false; 
 

 
\t function init_parallax() { 
 
\t \t win_h = win.height(); 
 
\t \t parallax_objs = []; 
 
\t \t parallaxers.each(function() { 
 
\t \t \t var cont = $(this), 
 
\t \t \t \t elem = cont.find('.parallax-image'), 
 
\t \t \t \t cont_top = cont.offset().top, 
 
\t \t \t \t cont_h = cont.height(), 
 
\t \t \t \t elem_h = Math.round(cont_h * 1.3), 
 
\t \t \t \t diff = elem_h - cont_h, 
 
\t \t \t \t max = Math.max(cont_h, win_h), 
 
\t \t \t \t speed = diff/max, 
 
\t \t \t \t parallaxer = { 
 
\t \t \t \t \t cont_top: cont_top, 
 
\t \t \t \t \t cont_h: cont_h, 
 
\t \t \t \t \t elem: elem, 
 
\t \t \t \t \t speed: speed 
 
\t \t \t \t }; 
 
\t \t \t parallax_objs.push(parallaxer); 
 
\t \t }); 
 
\t } 
 
    
 
    function on_scroll() { 
 
    if (!scroll_busy) { 
 
     scroll_busy = true; 
 
     window.requestAnimationFrame(init_scroll); 
 
    } 
 
    } 
 

 
    function init_scroll() { 
 
    scroll_events() 
 
    scroll_busy = false; 
 
    } 
 

 
    function scroll_events() { 
 
    var win_top = win.scrollTop(), 
 
     win_btm = win_top + win_h; 
 

 
\t \t $.each(parallax_objs, function(i, para) { 
 
\t \t \t cont_btm = para.cont_top + para.cont_h; 
 
\t \t \t if(cont_btm > win_top && para.cont_top <= win_btm) { 
 
\t \t \t \t var cont_scrolled = win_top - para.cont_top - para.cont_h, 
 
\t \t \t \t \t value = Math.round(cont_scrolled * para.speed); 
 
\t \t \t \t para.elem.css('top', value + 'px'); 
 
\t \t \t } 
 
\t \t }); 
 
    } 
 

 
    $(document).ready(function() { 
 
    \t init_parallax(); 
 
    win.resize(init_parallax); 
 
    scroll_events(); 
 
    win.scroll(on_scroll); 
 
    }); 
 

 
})(jQuery);
.parallax-window { 
 
    min-height: 300px; 
 
    position: relative; 
 
    overflow: hidden; 
 
} 
 

 
.parallax-window.lg { 
 
    min-height: 600px; 
 
} 
 

 
.parallax-image { 
 
    position: absolute; 
 
    top: 0; 
 
    left: 0; 
 
    width: 100%; 
 
    height: 130%; 
 
    background-size: cover; 
 
    background-repeat: no-repeat; 
 
    background-position: 50% 50%; 
 
    transform: translate3d(0, 0, 0); 
 
    z-index: -1; 
 
} 
 

 
.image-1 { 
 
    background-image: url(https://i.ytimg.com/vi/TbC-vUPMR7k/maxresdefault.jpg); 
 
} 
 

 
.image-2 { 
 
    background-image: url(https://i.ytimg.com/vi/xi5-YrAEChc/maxresdefault.jpg); 
 
} 
 

 
.parallax-content { 
 
    position: absolute; 
 
    top: 50%; 
 
    left: 0; 
 
    width: 100%; 
 
    text-align: center; 
 
    font-family: arial, sans-serif; 
 
    font-size: 60px; 
 
    color: #fff; 
 
    transform: translateY(-50%); 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
 
<div class="parallax-window lg"> 
 
    <div class="parallax-image image-1"></div> 
 
    <div class="parallax-content">Hello World</div> 
 
</div> 
 
<div class="parallax-window"> 
 
    <div class="parallax-image image-2"></div> 
 
    <div class="parallax-content">Hello World</div> 
 
</div> 
 
<div class="parallax-window lg"> 
 
    <div class="parallax-image image-1"></div> 
 
    <div class="parallax-content">Hello World</div> 
 
</div> 
 
<div class="parallax-window"> 
 
    <div class="parallax-image image-2"></div> 
 
    <div class="parallax-content">Hello World</div> 
 
</div> 
 
<div class="parallax-window lg"> 
 
    <div class="parallax-image image-1"></div> 
 
    <div class="parallax-content">Hello World</div> 
 
</div>

Mis à jour: https://jsfiddle.net/8dwLwgy7/2/