基于CSS3-perspective的视差滚动

html-css022

基于CSS3-perspective的视差滚动,第1张

前情提要:本篇文章已经默认你已经彻底了解perspective和translateZ的含义与用法,如果尚未了解,我推荐你看 css3系列之详解perspective

是不是比起普通网站多了一层酷炫?想知道如何实现吗?接下来我们进入part2。

步骤:

1.建立一个容器元素,设置 overflow-y: scroll 使其可以滚动(同时可能需要 overflow-x: hidden)。

2.对于上面的元素, 我们会应用一个 perspective 值,然后设置 perspective-origin 到 top left, 或者 0 0。

3.对上面元素的子元素应用一个在 Z 轴的变换,然后把它们还原回来以实现视差效果,而没有影响它们在屏幕上的大小。

这种方案下的css和html:

是不是很简单?

现在的你已经写出基本的视差滚动动画了!但是perspective和translateZ是怎么影响滚动速度的?还有scale,为什么这里设置的是3?想知道吗?那么接下来进入part3

这里把scale设为S,pespcetive->P,translateZ->D // 注意D一般是负值

那么有公式 S=(P-D)/P ,

这个公式怎么来的?这其实就是一个简单的相似三角形

划红线的地方的比例就是1:3,那么你只需要在原来的基础上放大3就可以让图形变回原来的比例,这里的1就是P,2就是D,那么很容易发现图形的缩小比例是P/(P-D),想放大回来?倒置这个缩小比例即可,我们便得到了S=(P-D)/P

现在我们已经靠scale属性让图形变回了原来的大小,似乎一切都恢复了原状,但有一个东西,它变了,便是滚动速度,滚动速度和上面的缩小比例是完全一致的,以如下数据为例

不看scale,这里的缩小比例是1/3,那么由于css机制,它的滚动速度也会变成原来的1/3。即使添加了scale属性,它的滚动速度依然不变还是原来的1/3。

现在让我们来总结性质:

父元素设置perspective,子元素设置 translateZ(-2px),那么无论是否有scale属性,

则有

PS:如果不设置 translateZ,或者 translateZ(0),那么对应D=0,所以有缩小比例=滚动速度比=(P/P-0)=1:1,即相对于原来的滚动速率不变。

为了方便读者尝试,我码了一个小小的demo,你可以任意更改属性来验证上面的结论!

参考文献

Performant Parallaxing : https://developers.google.com/web/updates/2016/12/performant-parallaxing

[杨耿]css3系列之详解perspective:

https://www.cnblogs.com/yanggeng/p/11285856.html

视差滚动(Parallax Scrolling)是指多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验。一般把网页解剖为:背景层、内容层和悬浮层(贴图层)。

当滚动鼠标滚轮的时候,各图层以不同速度移动,形成视差的效果。这就是时差滚动的大致原理。

原理是这样,但落实到技术细节上时,实现的方法却各种各样。

我个人大致归纳了一下:

1、以 “页面滚动条” 作为 “视差动画进度条” 的;

2、以 “滚轮刻度” 当作 “动画帧度” 去播放动画的(或者直接称为“隐藏进度条”);

3、鉴听mousewheel事件,事件被触发即播放动画,实现“翻页”效果;

下面的回答,均以上述1类的实现方式为基准。

为什么是1类呢?因为它很直观,和我们日常接触到的视频播放器是一样的:

下面,以Every Last Drop这个页面做为分析对象,去回答题主的问题。

做滚动网页的时候,是怎么实现页面的翻页?

首先,根据页面动画所需的分镜,去等比划分进度条。

例如:共有11个分镜,则分镜大致可以划分为:0%、10%、20%、30% .... 100%

但需要注意的是,整个滚动过程实际分为两个部分:分镜切换 和 分镜动画。

我们要预先划分好他们的比例,如:每一个分镜,2%的进度用于分镜切换,7%的进度用于分镜动画。

则进度大致可以划分为:

------------------------------------------

0%(初始,分镜1)

(消耗2%用于切换分镜)

2%(完全进入分镜2)

(消耗8%用于分镜动画的播放)

10%(分镜2动画播放完毕)

(消耗2%用于切换分镜)

12%(完全进入分镜3)

...(略)

------------------------------------------

按照上面的划分,当进度条滚动到10%的时候,就要开始进行分镜2到分镜3的切换,也就是所谓的翻页。当滚动到12%时,翻页结束。其他分镜如此类推。

(如果题主想问的是技术实现细节,估计要失望了!)

在做时间轴的时候,一般都要调用别人的js库。那么这个滚动页面,是不是也有一个js库?

随便在google搜一下,就搜到很多关于视差滚动插件的文章:10个优秀视差滚动插件

这里补充一点:做视差滚动页面绝对是体力活。

本着我为人人的分享精神,还是推荐一个我觉得好用凑合好用的时差滚动库:

Jarallax(Welcome to Jarallax.com)

设计思路清晰,API设计也很直观。依赖于jQuery1.7的版本,再高的版本就不支持了哦!

另外,作者貌似已经没有维护了...

滚动时每层不同滚动速率的实现原理是什么?

初中物理:单位时间相同,位移距离不同,速度也不同。

如何让滚动更加平滑?

这个问题就太大了,能重新开一个问题了。

这边我就简单回答一下吧(不细谈前端技术层面的优化,如:DOM数量、页面渲染优化这些)。

开头处,我提到的三种实现分类,实际上是这样一个情况:

1类是最自由的,用户甚至可以直接调整进度条,实现“快进”。

在这种设计下,用户鼠标滚轮的最小刻度,就是动画的一帧。因为不同浏览器之间,鼠标滚轮的最小刻度是不一样的。这就导致了,在不同浏览器之间,页面滚动过程中,动画播放的帧率是有差异的。如果遇到奇葩浏览器,鼠标滚动的最小刻度很大,动画甚至会出现“掉帧”的情况。

解决方法很简单,一般采取增加页面长度的方式,来稀释鼠标滚轮的最小刻度。

但还是会有一些情况出现,如户快拖动进度条时,“掉帧”的情况难免还是会出现。

3类的实现,滚轮只是动画的触发按钮。当用户滚动了一下鼠标,之前设计好的动画就开始播放。当播放结束后,对滚动事件的监听,才会重新被激活。这种设计,弱化了交互,但提供了更优质的动画展现。因为动画的播放时间和帧率不是用户控制的,是事先代码所设定好的。

2类就不说了,介乎与1和3之间。

简单的说,鱼(流畅)与熊掌(操控性)不可得兼。

       首先,我们来看一下什么叫 视差滚动 。视差滚动就是 让多层背景以不同的速度进行移动而形成的效果 。可能这句话不是很好理解,我们可以查看 这点网址 来直观的感受一下。

       当我们慢慢滚动页面的时候,会发现 产品主图 产品详情 滚动的速度不一致, 产品详情 以正常的速度进行滚动,但是 产品主图 要比 产品详情 滚动慢一倍,所以形成了 视差效果 。你也可以参照下面我给你贴出来的图:

可能从图上,不能直观的感受出来,建议您还是点看上面的网址,直观的感受一下。

        视察滚动:让多层背景以不同的速度去进行移动

       1、至少需要拥有两层背景(缓慢移动区、正常移动区)

       2、将背景设置为相对布局(为缓慢移动设置 top 来缓冲掉 scroll 滚动)

       3、监听 Parallax 组件的滑动,根据滑动来计算 缓慢移动区 top 的值。

       说白了,就是对 缓慢移动区 通过使用相对布局 relative &top 来弥补正常滚动产生的距离。话不多说,咱们码上见真情。

       考虑到可能要有多处使用到这个效果,所以,我们将其封装成组件,通过vue插槽的方式,来实现组件的复用。当然,这里我们默认,您对vue有比较好的掌握。

       模版中,我们使用了两个 slot ,分别接受 缓慢移动区 和 正常移动区 的内容,同时监听了 .parallax 的 scroll 事件,用于判定 缓慢移动区 距离顶部的距离。接着为 .parallax-slow 绑定了属性 :style="{top: slowTop}" , 确定滚动发生后,其距离顶部的距离。

       这里一定要注意 .parallax 一定要添加 position: absolute或者 position: fixed,否则,它的 scroll 事件不生效。具体的原因,你可以查看一写css相关的内容,此处不在多叙。

       另外就是 缓慢移动区 正常移动区 要设置 position:relative ,这个很重要。

       这个组件的行为主要是就是要计算 缓慢移动区 距离顶部的距离 top ,所有的工作都是围绕着这个逻辑进行实现的。

       我们在视图组件(Home)中使用 视差组件

        到此,我们的效果就可以实现了,那么为什么要使用这中效果呢?我个人觉效果是一方面,另一方面还是为了突出页面中的 重点元素 ,比如商品详情页面中, 产品主图 肯定是我们的重点元素,所以让他滑动的慢一些可以增强用户体验。为了照顾有些不喜欢阅读文章的同学,我将 Parallax 组件的内容贴出来。

        最后,感谢您的阅读,祝您学习进步。