且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

视差效果-滚动时计算子级到父级的偏移量

更新时间:2022-12-25 18:56:06

我知道了.

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

For anyone stumbling on this in the future - the trick was to replace the window scrolled value with the remainder of the window scrolled amount minus the element's offset top, minus the height of the element.

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

Then calculate the speed by dividing the difference between the container height and the element height with largest of either the window and the container:

// 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/