本文将介绍利用 CSS 实现滚动视差效果的一个小技巧,并且,利用这个技巧来制作一些有意思的交互特效。

关于使用 CSS 实现滚动视差效果,在之前有一篇文章详细描述过具体方案 - CSS 实现视差效果,感兴趣的同学可以先看看这篇文章。

这里,会运用上这样一种纯 CSS 的视差技巧:

使用 transform: translate3d 实现滚动视差

这里利用的是 CSS 3D,实现滚动视差效果。

原理就是:

  1. 我们给容器设置上 transform-style: preserve-3dperspective: xpx,那么处于这个容器的子元素就将位于3D空间中,

  2. 再给子元素设置不同的 transform: translateZ(),这个时候,不同元素在 3D Z轴方向距离屏幕(我们的眼睛)的距离也就不一样

  3. 滚动滚动条,由于子元素设置了不同的 transform: translateZ(),那么他们滚动的上下距离 translateY 相对屏幕(我们的眼睛),也是不一样的,这就达到了滚动视差的效果。

关于 transform-style: preserve-3d 以及 perspective 本文不做过多篇幅展开,默认读者都有所了解,还不是特别清楚的,可以先了解下 CSS 3D。

核心代码表示就是:

<div class="g-container">
<div class="section-one">translateZ(-1)</div>
<div class="section-two">translateZ(-2)</div>
<div class="section-three">translateZ(-3)</div>
</div>
html {
height: 100%;
overflow: hidden;
} body {
perspective: 1px;
transform-style: preserve-3d;
height: 100%;
overflow-y: scroll;
overflow-x: hidden;
} .g-container {
height: 150%; .section-one {
transform: translateZ(-1px);
}
.section-two {
transform: translateZ(-2px);
}
.section-three {
transform: translateZ(-3px);
}
}

总结就是父元素设置 transform-style: preserve-3dperspective: 1px,子元素设置不同的 transform: translateZ,滚动滚动条,效果如下:

CodePen Demo -- CSS 3D parallax

很明显,当滚动滚动条时,不同子元素的位移程度从视觉上看是不一样的,也就达到了所谓的滚动视差效果。

借助 CSS 视差实现酷炫交互动效

OK,有了上面的铺垫,我们来看看这样两个有趣的交互效果。由群里的日服第一切图仔 wheatup 友情提供。

先来看第一个效果:

效果是一种文本交替在不同高度的层展示,并且在滚动的过程中,会有明显的 3D 视差效果。

这个效果并不困难,核心就在于:

  1. 利用了 transform-style: preserve-3dperspective 构建不同的层次效果,制作视差效果
  2. 利用元素的 ::before::after 构建了 3D 的效果

我们看一个最小化 DEMO:

<div class="g-container">
<div class="g-box"></div>
<div class="g-box"></div>
<div class="g-box"></div>
</div>
.g-container {
height: 150vh;
perspective: 600px;
} .g-box {
width: 200px;
height: 200px;
background: #999;
transform-style: preserve-3d; &::before,
&::after {
content: "";
position: absolute;
right: 0;
left: 0;
transform-style: preserve-3d;
height: 200px;
background-color: #ccc;
}
&::before {
transform-origin: top center;
top: 0;
transform: rotateX(-90deg);
}
&::after {
transform-origin: bottom center;
bottom: 0;
transform: rotateX(90deg);
}
}

滚动 g-container 容器,即可得到一种 3D 效果:

由于还需要视差效果,我们需要给不同的层赋予不同的 translateZ(),我们稍微改造下代码,给每个 g-box 中间,再加多一层正常的 div,再给每个 g-box 加上一个 translateZ()

<div class="g-container">
<div class="g-box"></div>
<div class="g-normal"></div>
<div class="g-box"></div>
<div class="g-normal"></div>
<div class="g-box"></div>
</div>
.g-container {
width: 400px;
height: 150vh;
perspective: 800px;
} .g-normal {
width: 200px;
height: 200px;
background: #666;
transform-style: preserve-3d;
} .g-box {
width: 200px;
height: 200px;
background: #999;
transform-style: preserve-3d;
transform: translate3d(0, 0, 200px); &::before,
&::after {
// ... 保持不变
}
}
  1. 由于 g-boxg-normal 的 translateZ 值不同,所以滚动的过程中会出现视差效果
  2. 由于 g-boxtranslateZ 值为 translateZ(200px),两个伪元素的 rotateX 为正负 90deg,且高度为 200px,因此 g-boxg-normal 刚好可以通过 g-box 的两个伪元素衔接起来

最终,效果就是如上所示:

DEMO 的完整代码:CodePen Demo - 3D Parallax Scroll

CSS 滚动视差动画 2

OK,下面第二个滚动视差动画,也非常的有意思,想看看原版,也是来自于 wheatup 的 CodePen:

CodePen Demo -- 3D Chat Viewer

这里核心还是借助了 CSS 3D 的能力,但是由于使用的是滚动触发动画效果,并且有一定的从模糊到清晰的渐现效果,因此还是有一定的 JavaScript 代码。

感兴趣的可以看看上述的源码。

本文将尝试使用 CSS @Property 和 CSS 最新的特性 @scroll-timeline 还原该效果借助 JavaScript 实现的部分。

当然,首先不管是否需要借助 JavaScript,核心的 3D 部分使用的都是 CSS。

我们首先需要这样一个结构:

<div class="g-wrapper">
<div class="g-inner">
<div class="g-item"></div>
<div class="g-item"></div>
// ... 重复 N 个
</div>
</div>
.g-wrapper {
width: 100vw;
height: 100vh;
}
.g-inner {
position: relative;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
}
.g-item {
width: 300px;
height: 100px;
background: #000;
}

大概是这个效果:

然后,我们添加一些 CSS 3D 变换:

.g-wrapper {
// ... 与上述代码保持一致
perspective: 200px;
transform-style: preserve-3d;
}
.g-inner {
// ... 与上述代码保持一致
transform-style: preserve-3d;
transform: translateY(calc(-50% + 100px)) translateZ(0) rotateX(90deg);
transform-origin: bottom center;
}

就能得到这样一种视角的效果:

由于容器 g-inner 进行了一个绕 X 轴的 90deg 翻转,也就是 rotateX(90deg),所以,我们再给 g-item 一个反向的旋转,把卡片翻转回来:

.g-wrapper {
// ... 与上述代码保持一致
perspective: 200px;
transform-style: preserve-3d;
}
.g-inner {
// ... 与上述代码保持一致
transform-style: preserve-3d;
transform: translateY(calc(-50% + 100px)) translateZ(0) rotateX(90deg);
transform-origin: bottom center;
}
.g-item {
// ... 与上述代码保持一致
transform: rotateX(-90deg);
}

就能得到这样一种视角的效果:

此时,我们给容器一个赋予一个 translateZ 的动画:

.g-inner {
animation: move 10s infinite linear;
}
@keyframes move {
100% {
transform: translateY(calc(-50% + 100px)) translateZ(calc(100vh + 120px)) rotateX(90deg);
}
}

这样,整个动画的雏形就完成了,通过控制父元素的 perspective 大小和容器的 translateZ,得到了一种不断向视角面前位移的动画效果:

CodePen Demo -- CSS 3D Effect Demo

结合 CSS @scroll-timeline,利用 CSS 控制滚动与动画

那怎么利用 CSS 再把这个动画和滚动操作结合起来呢?

在前不久,我介绍过 CSS 的一个重磅特性 来了来了,它终于来了,动画杀手锏 @scroll-timeline,利用它可以实现 CSS 动画与滚动操作的结合,我们利用它改造一下代码:

<div class="g-scroll" id="g-scroll"></div>
<div class="g-wrapper">
<div class="g-inner">
<div class="g-item">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
// ... 重复 N 个
</div>
</div>
@property --phase {
syntax: '<length>';
inherits: false;
initial-value: 15px;
}
.g-scroll {
width: 100%;
height: 1000vh;
}
.g-wrapper {
position: fixed;
width: 100vw;
height: 100vh;
perspective: 200px;
transform-style: preserve-3d;
}
.g-inner {
position: relative;
height: 100%;
// 省略一些 flex 布局代码,与上文一致
transform-style: preserve-3d;
transform: translateY(calc(-50% + 100px)) translateZ(var(--phase)) rotateX(90deg);
transform-origin: bottom center;
animation-name: move;
animation-duration: 1s;
animation-timeline: box-move;
}
.g-item {
width: 300px;
height: 200px;
color: #fff;
background: #000;
transform: rotateX(-90deg);
}
@scroll-timeline box-move {
source: selector("#g-scroll");
orientation: "vertical";
}
@keyframes move {
0% {
--phase: 0;
}
100% {
--phase: calc(100vh + 100px);
}
}

这里相比上述的 DEMO,主要添加了 @scroll-timeline 的代码,我们增加了一个超长容器 .g-scroll,并且把它的滚动动作使用 @scroll-timeline box-move {} 规则和 animation-timeline: box-move 绑定了起来,这样,我们可以使用滚动去触发 @keyframes move {} CSS 动画。

效果如下:

在原效果中,还有一些使用 JavaScript 结合滚动距离控制的模糊的变化,这个,我们使用 backdrop-filter: blur() 也可以简单模拟。我们再简单添加一层 g-mask

<div class="g-scroll" id="g-scroll"></div>
<div class="g-wrapper">
<div class="g-mask"></div>
<div class="g-inner">
<div class="g-item">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
// ... 重复 N 个
</div>
</div>
// 其他保持一致
.g-mask {
position: fixed;
width: 100vw;
height: 100vh;
backdrop-filter: blur(5px);
transform: translateZ(0);
}

这样,基本就还原了原效果,并且,我们用且仅使用了 CSS:

CodePen Demo -- Pure CSS Scroll Animation 2(Chrome Only && Support ScrollTimeline)

总结一下

当然,本文后一个效果中,使用了非常多目前兼容性还非常差的 CSS 属性,尤其是 @scroll-timeline,仍然处于非常早期的阶段,兼容性一片红。但是不妨碍我们学习、感受 CSS 的美好。

要完全读懂本文,可能有一些前置知识需要了解,根据需要,你可以延伸阅读下:

好了,本文到此结束,希望对你有帮助

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

Amazing!巧用 CSS 视差实现酷炫交互动效的更多相关文章

  1. 使用纯 CSS 实现超酷炫的粘性气泡效果

    最近,在 CodePen 上看到这样一个非常有意思的效果: 这个效果的核心难点在于气泡的一种特殊融合效果. 其源代码在:CodePen Demo -- Goey footer,作者主要使用的是 SVG ...

  2. Android常用酷炫控件(开源项目)github地址汇总

    转载一个很牛逼的控件收集帖... 第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.Gri ...

  3. 用 CSS 实现酷炫的动画充电效果

    巧用 CSS 实现酷炫的充电动画 循序渐进,看看只使用 CSS ,可以鼓捣出什么样的充电动画效果. 画个电池 当然,电池充电,首先得用 CSS 画一个电池,这个不难,随便整一个: 欧了,勉强就是它了. ...

  4. 【CSS进阶】试试酷炫的 3D 视角

    写这篇文章的缘由是因为看到了这个页面: 戳我看看(移动端页面,使用模拟器观看) 运用 CSS3 完成的 3D 视角,虽然有一些晕3D,但是使人置身于其中的交互体验感觉非常棒,运用在移动端制作一些 H5 ...

  5. 15个来自 CodePen 的酷炫 CSS 动画效果【下篇】

    CodePen 是一个在线的前端代码编辑和展示网站,能够编写代码并即时预览效果.你在上面可以在线分享自己的 Web 作品,也可以欣赏到世界各地的优秀开发者在网页中实现的各种令人惊奇的效果. 今天这篇文 ...

  6. 赞!15个来自 CodePen 的酷炫 CSS 动画效果

    CodePen 是一个在线的前端代码编辑和展示网站,能够编写代码并即时预览效果.你在上面可以在线分享自己的 Web 作品,也可以欣赏到世界各地的优秀开发者在网页中实现的各种令人惊奇的效果. 今天这篇文 ...

  7. 一个酷炫的,基于HTML5,Jquery和Css的全屏焦点图特效,兼容各种浏览器

    基于HTML5和CSS的焦点图特效,梅花图案的背景很有中国特色,而且还会动哦,效果超炫,推荐下载! 演示图 html代码 <!DOCTYPE html PUBLIC "-//W3C// ...

  8. 学习animate.css包含了一组炫酷、有趣、跨浏览器的动画

    1.animate.css包含了一组炫酷.有趣.跨浏览器的动画,可以在你的项目中直接使用. 第一步:引入animate.css样式文件或者引入某些平台的CDN文件: <head> < ...

  9. 使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突

    使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种冲突 如果你还在为处理滑动冲突而发愁,那么你需要静 ...

随机推荐

  1. APUE1--3.8-3.10wirte、read函数以及IO效率

    1read函数 #include<unistd.h> ssize_t read(int fd,void* buf,size_t nbytes) 返回值:读到的字节数,若已到文件尾,返回0; ...

  2. 监听watch?

    对应一个对象,键是观察表达式,值是对应回调.值也可以是methods的方法名,或者是对象,包含选项.在实例化时为每个键调用 $watch()

  3. Jinkins流水线脚本使用curl命令调用服务接口,并且使用url传参。

    curl http://xxx.xx.xx.xx:xxxx/jenkins/publish?fileName=${fileName}&tag_name=${tag_name} 如图调用不符合c ...

  4. jQuery--基本事件总结

    基本事件介绍 blur() 失去焦点 change() 改变(select) click() 单机 dbclick() 双击 error() 页面异常 focus() 获得焦点 focusin() j ...

  5. JVM调优常用参数配置

    堆配置 -Xms:初始堆大小 -Xms:最大堆大小 -XX:NewSize=n:设置年轻代大小 -XX:NewRatio=n:设置年轻代和年老代的比值.如:为3表示年轻代和年老代比值为1:3,年轻代占 ...

  6. 在chrome浏览器英文环境下为什么上面现行代码不起作用?

    因为后面的客户端区域会覆盖前面的用户区域所以上面现行代码不起作用

  7. resin服务之一---安装及部署

    参考网站: http://caucho.com/ http://www.oschina.net/p/resin http://caucho.com/resin-4.0/admin/starting-r ...

  8. 【转】ng-class的用法

    原文出处:https://segmentfault.com/a/11... 在开发中我们通常会遇到一种需求:一个元素在不同的状态需要展现不同的样子. 而在这所谓的样子当然就是改变其css的属性,而实现 ...

  9. Android普通工具类获取Context

    在普通工具类中定义一个构造方法,类成员context,用于接收传过来的context 在activity中定义: 将context传过去. 在工具类中也可以使用SharePreferences,get ...

  10. java之String字符串根据指定字符转化为字符串数组

    public static void main(String[] args){ String str="护肤,药品,其他"; String temp[]; temp=str.spl ...