(2d illusion) Earth with Rotating Animation with CSS

  • Interactive CSS sphere
  • 最佳答案

    严格来说,平面屏幕上的任何“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/

    10-13 01:55