【问题标题】:Parallax effect - calculate child offset to parent on scroll视差效果 - 在滚动时计算子级到父级的偏移量
【发布时间】:2017-01-24 12:45:10
【问题描述】:

我正在尝试创建一种视差效果,即绝对定位的子元素在滚动时的移动速度应该比它的父元素慢。

孩子的高度总是父母的 130%,但父母可以是任何高度:

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);
}

我有一个移动图像的公式,但我的数学显然离题了:

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');
            }
        });
    }

图像移动但速度不正确。

当元素第一次进入视口时,图像应该与父元素的顶部对齐。然后滚动后,图像的底部到达视口顶部时应该与父级的底部对齐。

任何帮助将不胜感激!

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

【问题讨论】:

    标签: scroll parent offset parallax absolute


    【解决方案1】:

    我想通了。

    对于将来遇到此问题的任何人 - 诀窍是将窗口滚动值替换为窗口滚动量的剩余部分减去元素的偏移顶部,再减去元素的高度。

    然后通过容器高度和窗口和容器中最大的元素高度之间的差值来计算速度:

    // 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');
    

    完整的工作代码:

    (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();
    		parallaxers = $('.parallax-window'),
    		parallax_objs = [],
        scroll_busy = false;
    
    	function init_parallax() {
    		win_h = win.height();
    		parallax_objs = [];
    		parallaxers.each(function() {
    			var cont = $(this),
    				elem = cont.find('.parallax-image'),
    				cont_top = cont.offset().top,
    				cont_h = cont.height(),
    				elem_h = Math.round(cont_h * 1.3),
    				diff = elem_h - cont_h,
    				max = Math.max(cont_h, win_h),
    				speed = diff / max,
    				parallaxer = {
    					cont_top: cont_top,
    					cont_h: cont_h,
    					elem: elem,
    					speed: speed
    				};
    			parallax_objs.push(parallaxer);
    		});
    	}
      
      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;
    
    		$.each(parallax_objs, function(i, para) {
    			cont_btm = para.cont_top + para.cont_h;
    			if( cont_btm > win_top && para.cont_top <= win_btm ) {
    				var cont_scrolled = win_top - para.cont_top - para.cont_h,
    					value = Math.round(cont_scrolled * para.speed);
    				para.elem.css('top', value + 'px');
    			}
    		});
      }
    
      $(document).ready(function() {
      	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>

    更新小提琴:https://jsfiddle.net/8dwLwgy7/2/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-15
      • 2016-08-09
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多