服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - 编程技术 - 3D 穿梭效果?使用 CSS 轻松搞定

3D 穿梭效果?使用 CSS 轻松搞定

2021-11-08 23:21iCSS前端趣闻SbCoco 编程技术

打开 UU 加速器首页,瞬间,被它这个背景图吸引。出于对 CSS 的敏感,盲猜了一波这个是用 CSS 实现的,至少也应该是 Canvas。这么个背景图,CSS 不能搞定么?

3D 穿梭效果?使用 CSS 轻松搞定

背景

周末在家习惯性登陆 Apex,准备玩几盘。在登陆加速器的过程中,发现加速器到期了。

我一直用的腾讯网游加速器,然而点击充值按钮,提示最近客户端升级改造,暂不支持充值(这个操作把我震惊了~)。只能转头下载**网易 UU 加速器**[1]。

打开 UU 加速器首页,映入眼帘的是这样一幅画面:

3D 穿梭效果?使用 CSS 轻松搞定

瞬间,被它这个背景图吸引。

出于对 CSS 的敏感,盲猜了一波这个是用 CSS 实现的,至少也应该是 Canvas。打开控制台,稍微有点点失望,居然是一个 .mp4文件:

3D 穿梭效果?使用 CSS 轻松搞定

再看看 Network 面板,这个 .mp4 文件居然需要 3.5M?

3D 穿梭效果?使用 CSS 轻松搞定

emm,瞬间不想打游戏了。这么个背景图,CSS 不能搞定么?

使用 CSS 3D 实现星际 3D 穿梭效果

这个技巧,我在 奇思妙想 CSS 3D 动画 | 仅使用 CSS 能制作出多惊艳的动画?[2] 也有提及过,感兴趣的可以一并看看。

假设我们有这样一张图形:

3D 穿梭效果?使用 CSS 轻松搞定

这张图先放着备用。在使用这张图之前,我们会先绘制这样一个图形:

  1. "g-container">
  2. "g-group">
  3. "itemitem-right">
  4. "itemitem-left">
  5. "itemitem-top">
  6. "itemitem-bottom">
  7. "itemitem-middle">
  1. body{
  2. background:#000;
  3. }
  4. .g-container{
  5. position:relative;
  6. }
  7. .g-group{
  8. position:absolute;
  9. width:100px;
  10. height:100px;
  11. left:-50px;
  12. top:-50px;
  13. transform-style:preserve-3d;
  14. }
  15. .item{
  16. position:absolute;
  17. width:100%;
  18. height:100%;
  19. background:rgba(255,255,255,.5);
  20. }
  21. .item-right{
  22. background:red;
  23. transform:rotateY(90deg)translateZ(50px);
  24. }
  25. .item-left{
  26. background:green;
  27. transform:rotateY(-90deg)translateZ(50px);
  28. }
  29. .item-top{
  30. background:blue;
  31. transform:rotateX(90deg)translateZ(50px);
  32. }
  33. .item-bottom{
  34. background:deeppink;
  35. transform:rotateX(-90deg)translateZ(50px);
  36. }
  37. .item-middle{
  38. background:rgba(255,255,255,0.5);
  39. transform:rotateX(180deg)translateZ(50px);
  40. }

一共设置了 5 个子元素,不过仔细看 CSS 代码,其中 4 个子元素都设置了 rotateX/Y(90deg/-90deg),也就是绕 X 轴或者 Y 轴旋转了 90°,在视觉上是垂直屏幕的一张平面,所以直观视觉上我们是不到的,只能看到一个平面 .item-middle。

我将 5 个子 item 设置了不同的背景色,结果如下:

3D 穿梭效果?使用 CSS 轻松搞定

现在看来,好像平平无奇,确实也是。

不过,见证奇迹的时候来了,此时,我们给父元素 .g-container 设置一个极小的 perspective,譬如,设置一个 perspective: 4px,看看效果:

  1. .g-container{
  2. position:relative;
  3. +perspective:4px;
  4. }
  5. //...其余样式保持不变

此时,画风骤变,整个效果就变成了这样:

3D 穿梭效果?使用 CSS 轻松搞定

由于 perspective 生效,原本的平面效果变成了 3D 的效果。接下来,我们使用上面准备好的星空图,替换一下上面的背景颜色,全部都换成同一张图,神奇的事情发生了:

3D 穿梭效果?使用 CSS 轻松搞定

由于设置的 perspective 非常之小,而每个 item 的 transform: translateZ(50px) 设置的又比较大,所以图片在视觉上被拉伸的非常厉害。但是整体是充满整个屏幕的。

接下来,我们只需要让视角动起来,给父元素增加一个动画,通过控制父元素的 translateZ() 进行变化即可:

  1. .g-container{
  2. position:relative;
  3. perspective:4px;
  4. perspective-origin:50%50%;
  5. }
  6. .g-group{
  7. position:absolute;
  8. //...一些定位高宽代码
  9. transform-style:preserve-3d;
  10. +animation:move8sinfinitelinear;
  11. }
  12. @keyframesmove{
  13. 0%{
  14. transform:translateZ(-50px)rotate(0deg);
  15. }
  16. 100%{
  17. transform:translateZ(50px)rotate(0deg);
  18. }
  19. }

看看,神奇美妙的星空穿梭的效果就出来了,Amazing:

3D 穿梭效果?使用 CSS 轻松搞定

美中不足之处在于,动画没能无限衔接上,开头和结尾都有很大的问题。

当然,这难不倒我们,我们可以:

  1. 通过叠加两组同样的效果,一组相对另一组通过负的 animation-delay 提前行进,使两组动画衔接起来(一组结束的时候另外一组还在行进中)
  2. 再通过透明度的变化,隐藏掉 item-middle 迎面飞来的突兀感
  3. 最后,可以通过父元素的滤镜 hue-rotate 控制图片的颜色变化

我们尝试修改 HTML 结构如下:

  1. "g-container">
  2. "g-group">
  3. "itemitem-right">
  4. "itemitem-left">
  5. "itemitem-top">
  6. "itemitem-bottom">
  7. "itemitem-middle">
  8. --增加一组动画-->
  9. "g-group">
  10. "itemitem-right">
  11. "itemitem-left">
  12. "itemitem-top">
  13. "itemitem-bottom">
  14. "itemitem-middle">

修改后的核心 CSS 如下:

  1. .g-container{
  2. perspective:4px;
  3. position:relative;
  4. //hue-rotate变化动画,可以让图片颜色一直变换
  5. animation:hueRotate21sinfinitelinear;
  6. }
  7. .g-group{
  8. transform-style:preserve-3d;
  9. animation:move12sinfinitelinear;
  10. }
  11. //设置负的animation-delay,让第二组动画提前进行
  12. .g-group:nth-child(2){
  13. animation:move12sinfinitelinear;
  14. animation-delay:-6s;
  15. }
  16. .item{
  17. background:url(https://z3.ax1x.com/2021/08/20/fLwuMd.jpg);
  18. background-size:cover;
  19. opacity:1;
  20. //子元素的透明度变化,减少动画衔接时候的突兀感
  21. animation:fade12sinfinitelinear;
  22. animation-delay:0;
  23. }
  24. .g-group:nth-child(2).item{
  25. animation-delay:-6s;
  26. }
  27. @keyframesmove{
  28. 0%{
  29. transform:translateZ(-500px)rotate(0deg);
  30. }
  31. 100%{
  32. transform:translateZ(500px)rotate(0deg);
  33. }
  34. }
  35. @keyframesfade{
  36. 0%{
  37. opacity:0;
  38. }
  39. 25%,
  40. 60%{
  41. opacity:1;
  42. }
  43. 100%{
  44. opacity:0;
  45. }
  46. }
  47. @keyframeshueRotate{
  48. 0%{
  49. filter:hue-rotate(0);
  50. }
  51. 100%{
  52. filter:hue-rotate(360deg);
  53. }
  54. }

最终完整的效果如下,星空穿梭的效果,整个动画首尾相连,可以一直无限下去,几乎没有破绽,非常的赞:

3D 穿梭效果?使用 CSS 轻松搞定

上述的完整代码,你可以猛击这里:CSS 灵感 -- 3D 宇宙时空穿梭效果[3]

这样,我们就基本还原了上述见到的网易 UU 加速器首页的动图背景。

更进一步,一个图片我都不想用

当然,这里还是会有读者吐槽,你这里不也用了一张图片资源么?没有那张星空图行不行?这张图我也懒得去找。

当然可以,CSS YYDS。这里我们尝试使用 box-shadow,去替换实际的星空图,也是在一个 div 标签内实现,借助了 SASS 的循环函数:

  1. @functionrandomNum($max,$min:0,$u:1){
  2. @return($min+random($max))*$u;
  3. }
  4. @functionrandomColor(){
  5. @returnrgb(randomNum(255),randomNum(255),randomNum(255));
  6. }
  7. @functionshadowSet($maxWidth,$maxHeight,$count){
  8. $shadow:0000randomColor();
  9. @for$ifrom0through$count{
  10. $x:#{random(10000)/10000*$maxWidth};
  11. $y:#{random(10000)/10000*$maxHeight};
  12. $shadow:$shadow,#{$x}#{$y}0#{random(5)}pxrandomColor();
  13. }
  14. @return$shadow;
  15. }
  16. body{
  17. background:#000;
  18. }
  19. div{
  20. width:1px;
  21. height:1px;
  22. border-radius:50%;
  23. box-shadow:shadowSet(100vw,100vh,500);
  24. }

这里,我们用 SASS 封装了一个函数,利用多重 box-shadow 的特性,在传入的大小的高宽内,生成传入个数的点。

这样,我们可以得到这样一幅图,用于替换实际的星空图:

3D 穿梭效果?使用 CSS 轻松搞定

我们再把上述这个图,替换实际的星空图,主要是替换 .item 这个 class,只列出修改的部分:

  1. //原CSS,使用了一张星空图
  2. .item{
  3. position:absolute;
  4. width:100%;
  5. height:100%;
  6. background:url(https://z3.ax1x.com/2021/08/20/fLwuMd.jpg);
  7. background-size:cover;
  8. animation:fade12sinfinitelinear;
  9. }
  10. //修改后的CSS代码
  11. .item{
  12. position:absolute;
  13. width:100%;
  14. height:100%;
  15. background:#000;
  16. animation:fade12sinfinitelinear;
  17. }
  18. .item::after{
  19. content:"";
  20. position:absolute;
  21. top:0;
  22. left:0;
  23. right:0;
  24. bottom:0;
  25. width:1px;
  26. height:1px;
  27. border-radius:50%;
  28. box-shadow:shadowSet(100vw,100vh,500);
  29. }

这样,我们就实现了这样一个效果,在不借助额外资源的情况下,使用纯 CSS 实现上述效果:

3D 穿梭效果?使用 CSS 轻松搞定

CodePen Demo -- Pure CSS Galaxy Shuttle 2[4]

通过调整动画的时间,perspective 的值,每组元素的 translateZ() 变化距离,可以得到各种不一样的观感和效果,感兴趣的读者可以基于我上述给的 DEMO 自己尝试尝试。

最后

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

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

参考资料

[1]网易 UU 加速器:

https://uu.163.com/

[2]奇思妙想 CSS 3D 动画 | 仅使用 CSS 能制作出多惊艳的动画?:

https://github.com/chokcoco/iCSS/issues/132

[3]CSS 灵感 -- 3D 宇宙时空穿梭效果:

https://csscoco.com/inspiration/#/./3d/3d-css-galaxy-shuttle

[4]CodePen Demo -- Pure CSS Galaxy Shuttle 2:

https://codepen.io/Chokcoco/pen/NWvYOqW

原文链接:https://mp.weixin.qq.com/s/mQJAw8Zr1lLrRQIB2ml_AQ

延伸 · 阅读

精彩推荐