我尝试了视差实验,并从零开始了解这种魔术的核心部分。为了给你一个我喜欢用作灵感的例子,你可以在"照片"部分的这个链接上看到它。
最新代码包含相关信息。要全面了解问题,请参阅其他详细信息
我已经知道的核心部分是$window
的scrollTop()
和元素的offsetTop
对于在DOM元素上应用视差效果是重要的,以及对于效果应该对滚动速度有多敏感的factor
。最终结果应该是计算translateY
或translate3d
坐标(以像素或百分比为单位)的某种公式。
我在互联网上读到CSS属性translate
比position: absolute
中的top
更快,我更喜欢将translate与TweenMax GSAP结合使用。所以视差的移动会非常平滑。但是,如果只有css属性translate
就足够了,那也没关系。我看到了一些使用TweenMax的例子,所以这就是我现在使用它的原因。
JS
我有代码的基本东西:
var win = $(window);
var el = $('#daily .entry').find('figure');
win.scroll(function() {
var scrollTop = win.scrollTop();
var parallaxFactor = 5;
el.each(function() {
var image = $(this).find('img');
var offsetTop = $(this).offset().top;
// This is the part where I am talking about.
// Here should be the magic happen...
});
});
所以我在上面写了代码,但它当然什么都不做。请参阅上面代码中的CodePen。它将仅控制台日志scrollTop
和offsetTop
。如前所述,我只知道像scrollTop
和offsetTop
这样的核心部分来应用视差效果。然后应该创建一些区域,在那里会触发并发生视差效果,因此只会对视口中的元素进行计算,以保持良好的性能。之后应该做一些数学运算,但不知道具体是什么或如何实现。只有在我有了最终数字后,我才能在例如Greenstock的TweenMax
中使用它,就像这样:
TweenMax
TweenMax.to(image, 0.1, {
yPercent: offsetPercent + '%',
ease: Linear.easeNone
});
视差公式
如果我环顾四周,想把公式记下来,我会得到这样的东西(建立在互联网上):
var viewportOffset = scrollTop - offsetTop + win.height();
var offsetPercent = ((viewportOffset / win.height() * 100) - 100) / parallaxFactor;
if (viewportOffset >= 0 && viewportOffset <= win.height() * 2) {
TweenMax.to(image, 0.1, {
yPercent: offsetPercent + '%',
ease: Linear.easeNone
});
}
但如果我说实话,我不知道这到底是怎么回事,也不知道为什么会这样。我很想知道这一点,这样我就能理解视差产生的整个过程。scrollTop()
、offsetTop
和$(window).height()
的功能我很清楚,但这个公式背后的诀窍是什么,是我不明白的部分。
更新
更新1
@Scott已经通知灵感网站使用了一个名为scrollmagic.io的插件,但我很好奇如何在不使用插件的情况下自己创建视差。它是如何工作的,以及如何实现它。重点是公式,我为什么要这样或那样做,以及确切的计算结果,因为我不理解它,真的很想知道这一点,这样我就可以在未来应用视差效果时使用这些知识。
更新2
我试图弄清楚下面的代码片段到底做了什么。我说的是这个:
var viewportOffset = scrollTop - offsetTop + win.height();
经过一些良好的调试会话后,我认为我有了线索。所以scrollTop
是你向下滚动页面并隐藏在视图中的像素量。offsetTop
是元素在DOM中的起始位置,$(window).height
是视口高度(在浏览器中可见的部分)。
这就是我认为这个公式的作用:
将零点设置为元素的起点。例如,当scrollTop
等于0并且元素从顶部开始于240px
时,则公式为:0减去240即为-240
。因此当前滚动位置在零点以下。向下滚动240px后,公式将输出0,因为240减去240当然是0
(零)。我说得对吗?
但我还不明白为什么+ win.height
。如果我们回到上面的公式(在更新2),scrollTop为零,那么$(window).height
是从240px到视口底部的空间。向下滚动时,像素数量会随着滚动而增加,这对我来说毫无意义。如果有人能解释这可能是什么目的,那就好了。"I’我很好奇。第二部分计算视差CCD_ 28的公式我还不明白。一般情况下,计算卷轴上的视差强度。
更新3/4
在@Edisoni的建议下,我在过去几天里浏览了Travis Neilson的视频,我对视差的基本功能有了更多的了解。每个想挖掘视差的人都必须这样做。我已经用视差的新知识得到了我上面的脚本工作:
var root = this;
var win = $(window);
var offset = 0;
var elements = $('#daily .entry figure');
if (win.width() >= 768) {
win.scroll(function() {
// Get current scroll position
var scrollPos = win.scrollTop();
console.log(scrollPos);
elements.each(function(i) {
var elem = $(this);
var triggerElement = elem.offset().top;
var elemHeight = elem.height();
var animElem = elem.find('img');
if (scrollPos > triggerElement - (elemHeight / 2) && scrollPos < triggerElement + elemHeight + (elemHeight / 2)) {
// Do the magic
TweenMax.to(animElem, 0.1, {
yPercent: -(scrollPos - elemHeight / 2) / 100,
ease: Linear.easeNone
});
} else {
return false;
}
});
});
}
但是,脚本只适用于元素的某一部分。问题是它只适用于前两个元素。我怀疑"错误"位于if语句中的AND&&
符号之后,但无法解决错误。http://codepen.io/anon/pen/XKwBAB
当触发器上的元素设置动画时,它们会将一些像素跳到底部,不知道如何修复。触发后跳转到:1.135%
。所以它不会从0%开始。我已经检查过是否应该将CSS属性translate
添加到CSS中,并将数字类型设置为%
,但这对我不起作用
-webkit-transform: translateY(0%);
-moz-transform: translateY(0%);
-o-transform: translateY(0%);
transform: translateY(0%);
我应该使用TweenMax
.fromTo()
函数而不是使用.to()
函数,这样我也可以设置开始位置,还是我的想法是错误的,有不同的原因?
类似这样的东西:
TweenMax.fromTo(animElem, 0.1, {
yPercent: triggerElement,
z: 1
}, {
yPercent: -(scrollPos - elemHeight / 2) / 100,
ease: Linear.easeNone
});
除此之外,我试图在不使用scrollMagic插件的情况下重新创建我想用作灵感来源的网站的效果,但我真的不知道这是如何工作的,使用了两个不同的动画对象。
最后,如果有人认为代码可以更好地格式化,不要犹豫,我想听听你的建议
我的实际问题是针对更新2和3/4:
- 如何计算视差y坐标来完成"魔术">
- 关于更新2,零点将重置为每个元素的offsetTop,我说得对吗
- 为什么我的代码只适用于前两个元素,如果
translate
的内联样式将添加到动画元素中,为什么它们会跳下一些像素?有关所有信息,请参阅更新3/4
Parallax实际上在原理上非常简单。只需使视差元素的滚动速度慢于其他内容即可。也就是说,视差实现可以简单到将滚动距离除以一个因子:
var parallaxFactor = 3;
window.addEventListener("scroll", function(e){
el.style.top = (document.body.scrollTop / parallaxFactor) + "px";
// This is the magic. This positions the element's y-cord based off of the page scroll
}, false);
CODEPEN
这是视差效应的一个极其简单的演示。其他更彻底的实现可以将值处理为百分比,或者尝试使用TweenMax平滑动画。然而,这就是你正在寻找的魔法。
长命百岁。
更新:
此示例仅适用于屏幕顶部的元素。如果这是为了更通用的目的,您可能希望存储元素的默认y位置,然后是defaultYCord + (document.body.scrollTop / parallaxFactor)
行的内容。
更新2:
一个非常好的视差可视化来自Keith Clark,他制作了一个纯css视差滚动器:http://keithclark.co.uk/articles/pure-css-parallax-websites/demo3/.如果你点击左上角的debug,它会给你一个很好的魔术三维视图。
这不是如何在JS中构建视差的答案。但它显示了一些基础知识,如果你对代码太投入,这些基础知识往往会被遗忘。
基础知识:
- 在z层中对图形对象进行排序。z越高,距离越近它是在屏幕前观察
- 你的物体在z轴上越高,它在出现的东西上移动的速度就越快,比如你的滚动
- 现在你得到了一个3D效果,离你更近的物体随着离你更远的物体移动得更快
您的问题
如何计算视差y坐标来完成"魔术">
y位置取决于z索引。如果它很远,也就是z指数低,delta-y就小。如果它离你太近,delta-y就很大。请考虑z索引不一定用作Style属性,它看起来更像。我会给每个视差层添加一个类似data-z的属性。
function parallaxingY(el){
//el is a parallaxing element with attribute data-z
return $(el).data('z')*window.scrollTop;
}
建议的CSS解决方案很好,应该是首选。在那里,"魔法"——"z索引"——是由css样式的"scale"构成的。