视差效果 - 在滚动时计算子级到父级的偏移量 [英] Parallax effect - calculate child offset to parent on scroll

查看:20
本文介绍了视差效果 - 在滚动时计算子级到父级的偏移量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

子项将始终是父项的 130% 高度,但父项可以是任何高度:

HTML:

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

<div class="视差窗口"><div class="parallax-image image-2"></div><div class="parallax-content">Hello World</div>

CSS:

.parallax-window {最小高度:300px;位置:相对;溢出:隐藏;}.视差窗口.lg {最小高度:600px;}.视差图像{位置:绝对;顶部:0;左:0;宽度:100%;高度:130%;背景尺寸:封面;背景重复:不重复;背景位置:50% 50%;变换:translate3d(0, 0, 0);z-索引:-1;}.image-1 {背景图片:网址(https://i.ytimg.com/vi/TbC-vUPMR7k/maxresdefault.jpg);}.image-2 {背景图片:网址(https://i.ytimg.com/vi/xi5-YrAEChc/maxresdefault.jpg);}

我有一个移动图像的公式,但我的数学很明显:

var win = $(window),win_h = win.height(),parallaxers = $('.parallax-window');函数滚动事件(){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);如果 (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/)

解决方案

我想通了.

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

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

//错误://value = -Math.round((win_top * diff));//对:var diff = elem_h - cont_h,max = Math.max(cont_h, win_h),速度 = 差异/最大值,cont_scrolled = win_top - cont_top - cont_h,value = Math.round(cont_scrolled * speed);para.css('top', value + 'px');

完整的工作代码:

(function() {var lastTime = 0;var vendor = ['ms', 'moz', 'webkit', 'o'];for (var x = 0; x 

.parallax-window {最小高度:300px;位置:相对;溢出:隐藏;}.视差窗口.lg {最小高度:600px;}.视差图像{位置:绝对;顶部:0;左:0;宽度:100%;高度:130%;背景尺寸:封面;背景重复:不重复;背景位置:50% 50%;变换:translate3d(0, 0, 0);z-索引:-1;}.image-1 {背景图片:网址(https://i.ytimg.com/vi/TbC-vUPMR7k/maxresdefault.jpg);}.image-2 {背景图片:网址(https://i.ytimg.com/vi/xi5-YrAEChc/maxresdefault.jpg);}.视差内容{位置:绝对;顶部:50%;左:0;宽度:100%;文本对齐:居中;字体系列:arial、sans-serif;字体大小:60px;颜色:#fff;变换: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 class="视差窗口"><div class="parallax-image image-2"></div><div class="parallax-content">Hello World</div>

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

<div class="视差窗口"><div class="parallax-image image-2"></div><div class="parallax-content">Hello World</div>

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

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

I'm trying to create a parallax effect whereby an absolutely positioned child element should move at a rate slower than it's parent on scroll.

The child will always be 130% height of the parent but the parent can be any height:

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

I have a formula to move the image but my maths is clearly way off:

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

The images move but not at the correct rate.

The image should be in line with the top of the parent when the element first comes into the viewport. Then after scrolling, the bottom of the image should be in line with the bottom of the parent when it reaches the top of the viewport.

Any help would be massively appreciated!

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

解决方案

I figured this out.

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

Full working code:

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

Updated Fiddle: https://jsfiddle.net/8dwLwgy7/2/

这篇关于视差效果 - 在滚动时计算子级到父级的偏移量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆