3D 셔틀 효과를 만드는 방법은 무엇입니까? 가속화된 애니메이션 효과를 구현하시겠습니까? 다음 기사에서는 순수 CSS를 사용하여 쉽게 수행하는 방법을 소개합니다! 모두에게 도움이 되기를 바랍니다!
저는 습관적으로 주말에 집에서 Apex에 로그인하고 몇 가지 게임을 준비합니다. 액셀러레이터에 로그인하는 과정에서 액셀러레이터의 유효기간이 만료된 것을 발견했습니다.
저는 Tencent 온라인 게임 가속기를 사용하고 있는데 충전 버튼을 눌렀을 때 클라이언트가 최근 업그레이드되어 아직 충전을 지원하지 않는다는 메시지가 표시됩니다(이 작업은 충격적이었습니다~). 돌아서서 NetEase UU Accelerator만 다운로드할 수 있습니다.
UU Accelerator 홈페이지를 열면 다음 사진이 보입니다.
순간 이 배경 이미지에 매료됩니다.
CSS에 대한 민감성으로 인해 CSS로 구현해야 하고 최소한 Canvas여야 한다고 맹목적으로 추측했습니다. 콘솔을 열었을 때 .mp4
파일인 것으로 밝혀져 조금 실망했습니다. .mp4
文件:
再看看 Network
面板,这个 .mp4
文件居然需要 3.5M?
emm,瞬间不想打游戏了。这么个背景图,CSS 不能搞定么?
假设我们有这样一张图形:
这张图先放着备用。在使用这张图之前,我们会先绘制这样一个图形:
<div class="g-container"> <div class="g-group"> <div class="item item-right"></div> <div class="item item-left"></div> <div class="item item-top"></div> <div class="item item-bottom"></div> <div class="item item-middle"></div> </div> </div>
body { background: #000; } .g-container { position: relative; } .g-group { position: absolute; width: 100px; height: 100px; left: -50px; top: -50px; transform-style: preserve-3d; } .item { position: absolute; width: 100%; height: 100%; background: rgba(255, 255, 255, .5); } .item-right { background: red; transform: rotateY(90deg) translateZ(50px); } .item-left { background: green; transform: rotateY(-90deg) translateZ(50px); } .item-top { background: blue; transform: rotateX(90deg) translateZ(50px); } .item-bottom { background: deeppink; transform: rotateX(-90deg) translateZ(50px); } .item-middle { background: rgba(255, 255, 255, 0.5); transform: rotateX(180deg) translateZ(50px); }
一共设置了 5 个子元素,不过仔细看 CSS 代码,其中 4 个子元素都设置了 rotateX/Y(90deg/-90deg)
,也就是绕 X 轴或者 Y 轴旋转了 90°,在视觉上是垂直屏幕的一张平面,所以直观视觉上我们是不到的,只能看到一个平面 .item-middle
。
我将 5 个子 item 设置了不同的背景色,结果如下:
现在看来,好像平平无奇,确实也是。
不过,见证奇迹的时候来了,此时,我们给父元素 .g-container
设置一个极小的 perspective
,譬如,设置一个 perspective: 4px
,看看效果:
.g-container { position: relative; + perspective: 4px; } // ...其余样式保持不变
此时,画风骤变,整个效果就变成了这样:
由于 perspective
生效,原本的平面效果变成了 3D 的效果。接下来,我们使用上面准备好的星空图,替换一下上面的背景颜色,全部都换成同一张图,神奇的事情发生了:
由于设置的 perspective
非常之下,而每个 item 的 transform: translateZ(50px)
设置的又比较大,所以图片在视觉上被拉伸的非常厉害。但是整体是充满整个屏幕的。
接下来,我们只需要让视角动起来,给父元素增加一个动画,通过控制父元素的 translateZ()
进行变化即可:
.g-container{ position: relative; perspective: 4px; perspective-origin: 50% 50%; } .g-group{ position: absolute; // ... 一些定位高宽代码 transform-style: preserve-3d; + animation: move 8s infinite linear; } @keyframes move { 0%{ transform: translateZ(-50px) rotate(0deg); } 100%{ transform: translateZ(50px) rotate(0deg); } }
看看,神奇美妙的星空穿梭的效果就出来了,Amazing:
美中不足之处在于,动画没能无限衔接上,开头和结尾都有很大的问题。
当然,这难不倒我们,我们可以:
通过叠加两组同样的效果,一组比另一组通过负的 animation-delay
提前行进,使两组动画衔接起来(一组结束的时候另外一组还在行进中)
再通过透明度的变化,隐藏掉 item-middle
迎面飞来的突兀感
最后,可以通过父元素的滤镜 hue-rotate
Network
패널을 다시 보세요. 이 .mp4
파일에는 실제로 3.5M이 필요합니까?
emm , 더 이상 게임을하고 싶지 않습니다. CSS는 이런 배경 이미지를 처리할 수 없나요
?나중에 사용할 수 있도록 이 사진을 저장하세요. 이 그림을 사용하기 전에 먼저 다음과 같은 그래프를 그려보겠습니다.<div class="g-container"> <div class="g-group"> <div class="item item-right"></div> <div class="item item-left"></div> <div class="item item-top"></div> <div class="item item-bottom"></div> <div class="item item-middle"></div> </div> <!-- 增加一组动画 --> <div class="g-group"> <div class="item item-right"></div> <div class="item item-left"></div> <div class="item item-top"></div> <div class="item item-bottom"></div> <div class="item item-middle"></div> </div> </div>.g-container{ perspective: 4px; position: relative; // hue-rotate 变化动画,可以让图片颜色一直变换 animation: hueRotate 21s infinite linear; } .g-group{ transform-style: preserve-3d; animation: move 12s infinite linear; } // 设置负的 animation-delay,让第二组动画提前进行 .g-group:nth-child(2){ animation: move 12s infinite linear; animation-delay: -6s; } .item { background: url(https://z3.ax1x.com/2021/08/20/fLwuMd.jpg); background-size: cover; opacity: 1; // 子元素的透明度变化,减少动画衔接时候的突兀感 animation: fade 12s infinite linear; animation-delay: 0; } .g-group:nth-child(2) .item { animation-delay: -6s; } @keyframes move { 0%{ transform: translateZ(-500px) rotate(0deg); } 100%{ transform: translateZ(500px) rotate(0deg); } } @keyframes fade { 0%{ opacity: 0; } 25%, 60%{ opacity: 1; } 100%{ opacity: 0; } } @keyframes hueRotate { 0% { filter: hue-rotate(0); } 100% { filter: hue-rotate(360deg); } }총 5개의 하위 요소가 설정되어 있는데, CSS 코드를 잘 보면 그 중 4개가rotateX/Y(90deg)로 설정되어 있습니다. /-90deg)
, 즉 X축 또는 Y축을 기준으로 90° 회전한 경우 시각적으로 화면에 수직인 평면이므로 시각적으로 볼 수 없으며 한 평면만 볼 수 있습니다..item -중간
. 🎜🎜5개의 하위 항목에 대해 서로 다른 배경색을 설정했는데 결과는 다음과 같습니다. 🎜🎜🎜🎜이제 평범해 보이는데, 정말 그렇습니다. 🎜🎜그러나 이제 기적을 목격할 때가 왔습니다. 예를 들어, 상위 요소.g-container
에 대해 아주 작은perspective
를 설정했습니다.원근감: 4px
, 효과 보기: 🎜<div></div>🎜 이때 그림 스타일이 갑자기 바뀌었고 전체 효과는 다음과 같이 되었습니다: 🎜🎜🎜🎜perspective
적용으로 인해, 원래의 평면 효과가 3D 단일 효과가 되었습니다. 다음으로 위에서 준비한 별이 빛나는 하늘 이미지를 사용하고 위의 배경색을 교체한 후 모든 것을 동일한 이미지로 교체했습니다. 마법 같은 일이 일어났습니다: 🎜🎜🎜🎜perspective
설정이 매우 낮고 각 항목의 transform:transformZ(50px)가 상대적으로 크게 설정되어 이미지가 시각적으로 많이 늘어납니다. 하지만 모든 것이 화면 전체를 가득 채웁니다. 🎜🎜다음으로 원근감을 이동시키고, 상위 요소에 애니메이션을 추가하고, 상위 요소의translateZ()
를 제어하여 변경하면 됩니다. 🎜@function randomNum($max, $min: 0, $u: 1) { @return ($min + random($max)) * $u; } @function randomColor() { @return rgb(randomNum(255), randomNum(255), randomNum(255)); } @function shadowSet($maxWidth, $maxHeight, $count) { $shadow : 0 0 0 0 randomColor(); @for $i from 0 through $count { $x: #{random(10000) / 10000 * $maxWidth}; $y: #{random(10000) / 10000 * $maxHeight}; $shadow: $shadow, #{$x} #{$y} 0 #{random(5)}px randomColor(); } @return $shadow; } body { background: #000; } div { width: 1px; height: 1px; border-radius: 50%; box-shadow: shadowSet(100vw, 100vh, 500); }🎜마법과 멋진 별이 빛나는 하늘 셔틀 효과가 나옵니다, 놀랍습니다: 🎜🎜🎜🎜유일한 단점은 애니메이션이 무한히 연결되지 않고 시작과 끝 부분에 큰 문제가 있다는 점입니다. 🎜🎜물론 이것은 우리에게 문제가 되지 않습니다. 다음과 같이 할 수 있습니다. 🎜
- 🎜동일한 효과의 두 세트를 겹쳐서 한 세트는 음수입니다. 다른 세트
animation-delay
는 두 애니메이션 그룹을 연결하기 위해 미리 진행됩니다(한 그룹이 종료되면 다른 그룹은 여전히 진행 중입니다)🎜🎜- 🎜그런 다음 변경하여
를 숨깁니다. 투명도 항목-중간
갑자기 다가오는 느낌🎜🎜- 🎜마지막으로 상위 요소인
hue-rotate
🎜의 필터를 통해 이미지의 색상 변경을 제어할 수 있습니다. 🎜🎜🎜수정해 봅니다. HTML 구조는 다음과 같습니다. 🎜// 原 CSS,使用了一张星空图 .item { position: absolute; width: 100%; height: 100%; background: url(https://z3.ax1x.com/2021/08/20/fLwuMd.jpg); background-size: cover; animation: fade 12s infinite linear; } // 修改后的 CSS 代码 .item { position: absolute; width: 100%; height: 100%; background: #000; animation: fade 12s infinite linear; } .item::after { content: ""; position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 1px; height: 1px; border-radius: 50%; box-shadow: shadowSet(100vw, 100vh, 500); }🎜수정된 핵심 CSS는 다음과 같습니다. 🎜rrreee🎜최종 완성 효과는 다음과 같습니다. 별이 빛나는 하늘 왕복선의 효과, 전체 애니메이션이 연결되어 끝납니다. 끝으로, 거의 결함 없이 무한히 계속될 수 있습니다. 매우 칭찬합니다: 🎜🎜🎜🎜 🎜🎜위의 전체 코드를 보려면 여기를 클릭하세요: CSS 영감--3D 시공간 셔틀 효과🎜🎜https://csscoco .com/inspirion/#/./3d/3d-css-galaxy-shuttle🎜
这样,我们就基本还原了上述见到的网易 UU 加速器首页的动图背景。
当然,这里还是会有读者吐槽,你这里不也用了一张图片资源么?没有那张星空图行不行?这张图我也懒得去找。
当然可以,CSS YYDS。这里我们尝试使用 box-shadow
,去替换实际的星空图,也是在一个 div
标签内实现,借助了 SASS 的循环函数:
<div></div>
@function randomNum($max, $min: 0, $u: 1) { @return ($min + random($max)) * $u; } @function randomColor() { @return rgb(randomNum(255), randomNum(255), randomNum(255)); } @function shadowSet($maxWidth, $maxHeight, $count) { $shadow : 0 0 0 0 randomColor(); @for $i from 0 through $count { $x: #{random(10000) / 10000 * $maxWidth}; $y: #{random(10000) / 10000 * $maxHeight}; $shadow: $shadow, #{$x} #{$y} 0 #{random(5)}px randomColor(); } @return $shadow; } body { background: #000; } div { width: 1px; height: 1px; border-radius: 50%; box-shadow: shadowSet(100vw, 100vh, 500); }
这里,我们用 SASS 封装了一个函数,利用多重 box-shadow
的特性,在传入的大小的高宽内,生成传入个数的点。
这样,我们可以得到这样一幅图,用于替换实际的星空图:
我们再把上述这个图,替换实际的星空图,主要是替换 .item
这个 class,只列出修改的部分:
// 原 CSS,使用了一张星空图 .item { position: absolute; width: 100%; height: 100%; background: url(https://z3.ax1x.com/2021/08/20/fLwuMd.jpg); background-size: cover; animation: fade 12s infinite linear; } // 修改后的 CSS 代码 .item { position: absolute; width: 100%; height: 100%; background: #000; animation: fade 12s infinite linear; } .item::after { content: ""; position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 1px; height: 1px; border-radius: 50%; box-shadow: shadowSet(100vw, 100vh, 500); }
这样,我们就实现了这样一个效果,在不借助额外资源的情况下,使用纯 CSS 实现上述效果:
CodePen Demo -- Pure CSS Galaxy Shuttle 2:
https://codepen.io/Chokcoco/pen/NWvYOqW
通过调整动画的时间,perspective
的值,每组元素的 translateZ()
变化距离,可以得到各种不一样的观感和效果,感兴趣的读者可以基于我上述给的 DEMO 自己尝试尝试。
好了,本文到此结束,希望本文对你有所帮助 :)
(学习视频分享:web前端教程)
위 내용은 순수 CSS를 사용하여 3D 셔틀 효과 만들기(코드 첨부)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!