(2d illusion) Earth with Rotating Animation with CSS
最佳答案
严格来说,平面屏幕上的任何“3D”形状更像是 3D 对象的幻觉。我们所看到的只是屏幕平面上该形状的 2D 投影,我们的大脑会尽力猜测哪种形状可以提供我们看到的投影。如果投影发生变化,我们的大脑会将其解释为改变其方向的 3D 对象,这有助于它更好地确定该对象的形状。
它适用于非对称物体和由多边形(例如立方体)制成的物体,但球体是一个非常特殊的情况:它在平面上的投影总是只给出一个圆。静止球体和旋转球体具有相同的投影,相同的圆。即使在现实生活中,如果我们观察一个表面均匀且没有任何标记的球体(例如,一个抛光的金属球),也很难确定它是静止还是旋转。我们的眼睛需要一些提示,一些根据球体的几何形状沿着球体表面移动的细节。此类细节越多,球面上的点以您期望的方式移动,旋转球体的感知(好吧,错觉)就越清晰。
这里是制作一个能够提供这种感知的 CSS 场景的关键:为了使这种错觉足够强大,我们需要许多标记沿着位于不同平面的路径移动。在 CSS 中实现这一点的唯一方法是将每个标记作为一个单独的 CSS 框(元素或伪元素)。如果我们的球体仅由移动标记组成,我们真的需要很多标记才能将其视为一个球体——因此在您看过的大多数演示中,“数百个元素”。
因此,如果您想使用少量元素使球体看起来逼真,则可能需要结合使静态基本球形(具有径向渐变、内部阴影等的圆形)“错觉”的效果。使用一些相对较小的元素(以使其不那么明显,它们实际上是平坦的),沿着球体表面定向并使用 3D 变换进行动画处理 — 与第一个演示中的立方体表面的方式基本相同。
下面是我自己将这种方法付诸实践的尝试。我使用了 20 个圆形元素,大致作为 regular icosahedron 的面(就像经典足球上的白色六边形)。为了方便起见,我将它们分成两组,每组制作一个半球(这不是必需的,但它使造型更简单一些)。整个 3D 场景由球体本身和背景框架(伪元素)组成,背景框架在球体中心附近穿过球体(靠近一点,以减少圆圈从近侧到远侧和返回时的“闪烁” ) 并始终面向屏幕。所以总共有 24 个元素(至少不是字面上的“数百个”:)。为了使圆圈看起来更“凸出”(如球段),我为每个圆圈添加了两个伪元素,并将它们稍微抬高。在 Chrome 和 Firefox 57+ 中效果最佳(在 Firefox 56- 和 iOS Safari 中,边缘附近仍有一些“闪烁”)。如果您将圆悬停在圆圈上,您可以看到没有背景框(也没有“闪烁”)的场景。也有一个稍微修改的版本 on Codepen 。
.scene {
perspective: 400vmin;
transform-style: preserve-3d;
position: absolute;
width: 80vmin;
height: 80vmin;
top: 10vmin;
left: 10vmin;
}
.sphere {
transform-style: preserve-3d;
position: absolute;
animation: rotate 20s infinite linear;
width: 100%;
height: 100%;
transform-origin: 50% 50%;
top: 0;
left: 0;
}
.scene::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0%;
left: 0%;
background: radial-gradient(circle farthest-corner at 33% 33%, rgba(240, 240, 220, 0.85) 0%, rgba(30, 30, 40, 0.85) 80%), radial-gradient(circle farthest-corner at 45% 45%, rgba(0, 0, 0, 0) 50%, #000000 80%);
border-radius: 50%;
transform: translateZ(2vmin);
}
.scene:hover::before {
display: none;
}
.hemisphere {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform-origin: 50% 50%;
transform: rotateX(90deg);
}
.hemisphere:nth-child(2) {
transform: rotateX(-90deg);
}
.face {
position: absolute;
width: 40vmin;
height: 40vmin;
background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 48%, #ff0000 49%, #ff0000 50%, rgba(0, 0, 0, 0) 51%);
transform-style: preserve-3d;
transform-origin: 50% 0;
top: 50%;
left: 20vmin;
}
.face::before, .face::after {
content: '';
position: absolute;
border-radius: 50%;
box-sizing: border-box;
}
.face::before {
width: 50%;
height: 50%;
top: 25%;
left: 25%;
border: 2px solid #333;
background: rgba(255, 255, 255, 0.3);
transform: translateZ(1.6vmin);
}
.face::after {
width: 20%;
height: 20%;
top: 40%;
left: 40%;
background: rgba(0, 0, 0, 0.2);
transform: translateZ(2.8vmin);
}
.face:nth-child(1) {
transform: translateZ(-41.6vmin) rotateZ(36deg) translateY(-6.8vmin) rotateX(143deg);
}
.face:nth-child(2) {
transform: translateZ(-41.6vmin) rotateZ(108deg) translateY(-6.8vmin) rotateX(143deg);
}
.face:nth-child(3) {
transform: translateZ(-41.6vmin) rotateZ(180deg) translateY(-6.8vmin) rotateX(143deg);
}
.face:nth-child(4) {
transform: translateZ(-41.6vmin) rotateZ(252deg) translateY(-6.8vmin) rotateX(143deg);
}
.face:nth-child(5) {
transform: translateZ(-41.6vmin) rotateZ(-36deg) translateY(-6.8vmin) rotateX(143deg);
}
.face:nth-child(6) {
transform: translateZ(-26.8vmin) rotateZ(36deg) translateY(-33.2vmin) rotateX(100deg);
}
.face:nth-child(7) {
transform: translateZ(-26.8vmin) rotateZ(108deg) translateY(-33.2vmin) rotateX(100deg);
}
.face:nth-child(8) {
transform: translateZ(-26.8vmin) rotateZ(180deg) translateY(-33.2vmin) rotateX(100deg);
}
.face:nth-child(9) {
transform: translateZ(-26.8vmin) rotateZ(252deg) translateY(-33.2vmin) rotateX(100deg);
}
.face:nth-child(10) {
transform: translateZ(-26.8vmin) rotateZ(-36deg) translateY(-33.2vmin) rotateX(100deg);
}
.face:nth-child(11) {
transform: translateZ(-26.8vmin) rotateZ(36deg) translateY(-33.2vmin) rotateX(100deg);
}
@keyframes rotate {
0% {
transform: rotateZ(25deg) rotateX(20deg) rotateY(0deg);
}
50% {
transform: rotateZ(-25deg) rotateX(-20deg) rotateY(180deg);
}
100% {
transform: rotateZ(25deg) rotateX(20deg) rotateY(360deg);
}
}
body {
background: #555;
overflow: hidden;
}
<div class="scene">
<div class="sphere">
<div class="hemisphere">
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
</div>
<div class="hemisphere">
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
<div class="face"></div>
</div>
</div>
</div>
关于css - 如何创建纯 CSS 3 维球体?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45238194/