RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 941545
Accepted
Alexandr_TT
Alexandr_TT
Asked:2020-02-06 21:17:25 +0000 UTC2020-02-06 21:17:25 +0000 UTC 2020-02-06 21:17:25 +0000 UTC

如何在 CSS 中创建 3D 球体?

  • 772

我尝试仅使用纯 CSS 创建 3D 球体,但无法生成所需的形状。我见过 цилиндр ,但我找不到创建真实球体的链接。

.red {
  background-color: red;
}
.green {
  background-color: green;
}
.blue {
  background-color: blue;
}
.yellow {
  background-color: yellow;
}
.sphere {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  text-align: center;
  vertical-align: middle;
  font-size: 500%;
  position: relative;
  box-shadow: inset -10px -10px 100px #000, 10px 10px 20px black, inset 0px 0px 10px black;
  display: inline-block;
  margin: 5%;
}
.sphere::after {
  background-color: rgba(255, 255, 255, 0.3);
  content: '';
  height: 45%;
  width: 12%;
  position: absolute;
  top: 4%;
  left: 15%;
  border-radius: 50%;
  transform: rotate(40deg);
}
<div class="sphere red"></div>
<div class="sphere green"></div>
<div class="sphere blue"></div>
<div class="sphere yellow"></div>
<div class="sphere"></div>

然而:

  • 答:这些只是 2D 圆,不是 3D 形状
  • B:我不能像球图像一样在 3d 中旋转它们(我想要一个旋转图像)。
javascript
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    Misha Saidov
    2020-02-10T18:06:03Z2020-02-10T18:06:03Z

    我试过了。

    我不太明白讨论了哪些未上漆的部分。在该示例中叠加的贴图本身在侧面有一个 Alpha 通道。编写一个覆盖椭圆地图的算法将非常困难(以至于有人可能会说不可能),但我注意到这一切为时已晚,此时我已经编写了大部分球体代码。

    Не сказать, что получилось чем-то лучше, но хоть геометрию вспомнил :) Код полностью мой, к @ZulNs не подглядывал, если необходимо - дам комментарий по любой интересующей строке. Для веселья добавил выбор карт :) Собственно вот:

    class Sphere {
      constructor(props) {
        props = (props.constructor.name === "Object" ? props : {});
        this.element = (props.element instanceof HTMLElement ? props.element : document.body);
        this.radius = (typeof props.radius === "number" ? props.radius : 100);
        this.polygonsPerMeridian = (typeof props.polygonsPerMeridian === "number" ? props.polygonsPerMeridian : 15);
        this.texture = (typeof props.texture === "string" ? props.texture : "none");
        this.rotate = (typeof props.rotate === "boolean" ? props.rotate : true);
        this.rotationTime = (typeof props.rotationTime === "number" ? props.rotationTime : 10);
        this.diameter = this.radius * 2;
        this.polygonSize = Math.ceil(this.radius * (2 * Math.tan(Math.PI / ((this.polygonsPerMeridian - 1) * 2))));
        this.parts = {
          sphere: null,
          meridians: [],
          polygons: []
        };
        this.handlers = {
          createSphereElement: () => {
            let sphere = document.createElement("div");
            sphere.classList.add("sphere");
            sphere.style.width = `${this.diameter}px`;
            sphere.style.height = `${this.diameter}px`;
            this.rotate && (sphere.style.animation = `rotate linear ${this.rotationTime}s infinite`);
            this.parts.sphere = sphere;
            return sphere;
          },
          createMeridianElement: () => {
            let meridian = document.createElement("div");
            meridian.classList.add("meridian");
            this.parts.meridians.push(meridian)
            return meridian;
          },
          createPolygonElement: (m, p) => {
            let x = this.radius * Math.cos((p * (Math.PI * 2)) / (this.polygonsPerMeridian - 1));
            let scaleXK = (1 - (.2 * (100 - (((this.radius - x) * 100) / (this.radius * 2))) / 100));
    
            let polygon = document.createElement("div");
            polygon.classList.add("polygon");
            polygon.style.backgroundImage = `url('${this.texture}')`;
            polygon.style.backgroundPosition = `${-m * this.polygonSize}px ${-(p * this.polygonSize)}px`;
            polygon.style.backgroundSize = `${((this.polygonsPerMeridian - 1) * 2) * this.polygonSize}px ${this.polygonsPerMeridian * this.polygonSize}px`;
            polygon.style.backgroundColor = `rgb(${0}, ${0}, ${(p * 255) / this.polygonsPerMeridian})`;
            polygon.style.transformOrigin = `center center ${-this.radius}px`;
            polygon.style.width = `${this.polygonSize}px`;
            polygon.style.height = `${this.polygonSize}px`;
            polygon.style.transition = "all 1s ease-in-out";
            polygon.style.transform = `translateX(${((this.diameter / 2) - (this.polygonSize / 2))}px) translateY(${((this.diameter / 2) - (this.polygonSize / 2))}px) translateZ(${this.radius}px) rotateY(${(m * (180 * 2)) / ((this.polygonsPerMeridian - 1) * 2)}deg) rotateZ(${((p * 180) / (this.polygonsPerMeridian - 1)) - 90}deg) rotate3d(0, 1, 0, 90deg) scaleX(${scaleXK})`;
            return polygon;
          },
          renderSphere: () => {
            let sphere = this.handlers.createSphereElement();
            for (let m = 0; m < ((this.polygonsPerMeridian - 1) * 2); m++) {
              let meridian = this.handlers.createMeridianElement();
              for (let p = 0; p < this.polygonsPerMeridian; p++) {
                let polygon = this.handlers.createPolygonElement(m, p);
                this.parts.polygons.push(polygon);
                meridian.appendChild(polygon);
                sphere.appendChild(meridian);
              }
            }
            this.element.appendChild(sphere);
          }
        }
        this.handlers.renderSphere();
      }
    
      setTexture(texture) {
        this.texture = (typeof texture === "string" ? texture : "none");
        this.parts.polygons.forEach(item => item.style.backgroundImage = `url('${texture}')`);
      }
    }
    
    new Sphere({
      element: document.body,
      radius: 150,
      polygonsPerMeridian: 13,
      texture: "https://cdn.thinglink.me/api/image/743786736932356097/1240/10/scaletowidth",
      rotate: true,
      rotationTime: 10,
    });
    
    new Sphere({
      element: document.body,
      radius: 50,
      polygonsPerMeridian: 13,
      texture: "https://static-2.gumroad.com/res/gumroad/5387571460549/asset_previews/b455aaa72d1482e171f0558c2766cd48/retina/Mars_2k_Color_Preview_v001.jpg",
      rotate: true,
      rotationTime: 20,
    });
    
    new Sphere({
      element: document.body,
      radius: 30,
      polygonsPerMeridian: 13,
      texture: "https://static-2.gumroad.com/res/gumroad/5387571460549/asset_previews/d7c3b214de778aa83aa0a0ab32eec4c1/retina/Moon_2k_Preview.jpg",
      rotate: true,
      rotationTime: 5,
    });
    body {
      padding: 10px;
      display: flex;
      flex-wrap: wrap;
    }
    
    .sphere {
      position: relative;
      transform-style: preserve-3d;
    }
    
    .meridian {
      transform-style: preserve-3d;
    }
    
    .polygon {
      position: absolute;
      margin: auto;
      background-repeat: no-repeat;
      backface-visibility: hidden;
    }
    
    @keyframes rotate {
      from {
        transform: rotate3d(1, 1, 0, 0deg);
      }
      to {
        transform: rotate3d(1, 1, 0, 360deg);
      }
    }

    На вход радиус, кол-во полигонов на один меридиан и картинка, желательно прямоугольная, без альфа-каналов. Если на вход будет квадратная картинка то она растянется до нужных размеров.

    Минусы:

    1. У полюсов, там, где искажение карты наиболее сильное, полигоны накладываются друг на друга ибо не имеют "меридианной" перспективы. В коде это частично решается при помощи сложно формулы расчета scaleX полигона ближе к полюсам (scaleXK), но и это не помогает в полной мере. Это самый основной минус, но думаю я продолжу работать над скриптом и поправлю это дело.
    2. Иногда появляются щели между полигонами. Скорей всего это проблема позиционирования элементов браузером, т.к. формулы расчета размера полигонов правильные. Хотфикс: добавление нескольких пикселей к размеру полигона.

    Плюсы:

    1. Код довольно компактный, если опустить кучу строк, которые уходят на создание селекта и на хранение ссылок карт в параметрах.
    2. Масштабируемость
    3. Анимацией занимается графический ускоритель

    В идеале можно превратить весь код в класс, чтобы можно было создавать кучу сфер с разными параметрами. Буду рад, если более опытные программисты тоже помогут в устранение минусов.

    UPD 10.02.2019: Реализовал классы. Теперь удобно создавать новые сферы, можете оценить на примере 3-х планет с разными временем вращения, размером и детализацией.

    UPD 11.02.2019: Добавил новы метод setTexture(textureSrc). С его помощью можно плавно менять текстуру "на лету". Оформил небольшой репозиторий на GitHub.

    • 21
  2. Kvilios
    2020-02-06T21:47:32Z2020-02-06T21:47:32Z

    纯粹在 CSS 中,什么都没有,但是来自您使用这样的圆柱体发送的同一系列(来源):

    $(function() {
    
      var el = document.createElement('div'),
        transformProps = 'transform WebkitTransform MozTransform OTransform msTransform'.split(' '),
        transformProp = support(transformProps);
    
      function support(props) {
        for (var i = 0, l = props.length; i < l; i++) {
          if (typeof el.style[props[i]] !== "undefined") {
            return props[i];
          }
        }
      }
    
      var $sphere = $('#sphere'),
        sphere = {
          rounds: 8,
          panels: 24,
          panelWidth: 100,
          el: $sphere.find('.container'),
          build: function(p, r) {
    
            var panels = p || this.panels,
              rounds = r || this.rounds,
              rotationPerPanel = 360 / panels,
              rotationPerRound = 360 / 2 / rounds,
              yRotation,
              xRotation,
              width = this.panelWidth,
              zTranslate = (width / 2) / Math.tan(rotationPerPanel * Math.PI / 180),
              $container = this.el,
              $ul,
              $li,
              i, j;
    
            this.el.html('');
            for (i = 0; i < rounds; i++) {
              $ul = $('<ul>');
              xRotation = rotationPerRound * i;
              $ul[0].style[transformProp] = "rotateX(" + xRotation + "deg)";
              for (j = 0; j < panels; j++) {
                $li = $('<li>');
                yRotation = rotationPerPanel * j;
                $li[0].style[transformProp] = "rotateY(" + yRotation + "deg) translateZ(" + zTranslate + "px)";
                $ul.append($li);
              }
              $container.append($ul);
            }
          }
        },
        mouse = {
          start: {}
        },
        touch = document.ontouchmove !== undefined,
        viewport = {
          x: 0,
          y: 0,
          el: $('#sphere .container')[0],
          move: function(coords) {
            if (coords) {
              if (typeof coords.x === "number") this.x = coords.x;
              if (typeof coords.y === "number") this.y = coords.y;
            }
            this.el.style[transformProp] = "rotateX(" + this.x + "deg) rotateY(" + this.y + "deg)";
          },
          reset: function() {
            this.move({
              x: 0,
              y: 0
            });
          }
        };
    
      sphere.build();
    
      $(document).keydown(function(evt) {
        switch (evt.keyCode) {
          case 37: // left
            viewport.move({
              y: viewport.y - 90
            });
            break;
    
          case 38: // up
            evt.preventDefault();
            viewport.move({
              x: viewport.x + 90
            });
            break;
    
          case 39: // right
            viewport.move({
              y: viewport.y + 90
            });
            break;
    
          case 40: // down
            evt.preventDefault();
            viewport.move({
              x: viewport.x - 90
            });
            break;
    
          case 27: //esc
            viewport.reset();
            break;
    
          default:
            break;
        };
      }).bind('mousedown touchstart', function(evt) {
        delete mouse.last;
    
        evt.originalEvent.touches ? evt = evt.originalEvent.touches[0] : null;
        mouse.start.x = evt.pageX;
        mouse.start.y = evt.pageY;
        $(document).bind('mousemove touchmove', function(event) {
          // Only perform rotation if one touch or mouse (e.g. still scale with pinch and zoom)
          if (!touch || !(event.originalEvent && event.originalEvent.touches.length > 1)) {
            event.preventDefault();
            // Get touch co-ords
            event.originalEvent.touches ? event = event.originalEvent.touches[0] : null;
            $sphere.trigger('move-viewport', {
              x: event.pageX,
              y: event.pageY
            });
          }
        });
    
        $(document).bind('mouseup touchend', function() {
          $(document).unbind('mousemove touchmove');
        });
      });
    
      $sphere.bind('move-viewport', function(evt, movedMouse) {
    
        // Reduce movement on touch screens
        var movementScaleFactor = touch ? 4 : 1;
    
        if (!mouse.last) {
          mouse.last = mouse.start;
        } else {
          if (forward(mouse.start.x, mouse.last.x) != forward(mouse.last.x, movedMouse.x)) {
            mouse.start.x = mouse.last.x;
          }
          if (forward(mouse.start.y, mouse.last.y) != forward(mouse.last.y, movedMouse.y)) {
            mouse.start.y = mouse.last.y;
          }
        }
    
        viewport.move({
          x: viewport.x + parseInt((mouse.start.y - movedMouse.y) / movementScaleFactor),
          y: viewport.y - parseInt((mouse.start.x - movedMouse.x) / movementScaleFactor)
        });
    
        mouse.last.x = movedMouse.x;
        mouse.last.y = movedMouse.y;
    
        function forward(v1, v2) {
          return v1 >= v2;
        }
      });
    
      /* Change sphere style */
      $('#controls').bind('submit change', function(evt) {
        evt.preventDefault();
        $sphere.attr('class', '').addClass($(evt.target).val());
      });
    });
    #sphere {
      width: 100px;
      height: 100px;
      margin: 200px auto;
      -webkit-perspective: 800px;
      -moz-perspective: 800px;
      perspective: 800px;
    }
    
    .container {
      width: 100px;
      height: 100px;
      -webkit-transition: -webkit-transform 200ms linear;
      -webkit-transform-style: preserve-3d;
      -moz-transition: -moz-transform 200ms linear;
      -moz-transform-style: preserve-3d;
      transition: transform 200ms linear;
      transform-style: preserve-3d;
    }
    
    .container>ul {
      -webkit-transform-style: preserve-3d;
      -moz-transform-style: preserve-3d;
      transform-style: preserve-3d;
      width: 100%;
      height: 100%;
      position: absolute;
    }
    
    .container li {
      width: 98px;
      height: 98px;
      position: absolute;
      display: block;
      background: #000;
      border: 1px solid #fff;
      opacity: 0.1;
      border-radius: 50px;
    }
    
    
    /* Different spheres */
    
    
    /*************************************************/
    
    
    /* Square */
    
    #sphere.square li {
      border-radius: 0;
    }
    
    
    /* Kaleidoscope */
    
    #sphere.kaleidoscope li {
      opacity: 0.9;
      -webkit-animation: borderRadius 5s linear infinite alternate;
      -moz-animation: borderRadius 5s linear infinite alternate;
      animation: borderRadius 5s linear infinite alternate;
    }
    
    
    /* Eye */
    
    #sphere.eye li {
      opacity: 0.5;
      background: #fff;
    }
    
    #sphere.eye li:nth-child(7),
    #sphere.eye li:nth-child(8),
    #sphere.eye li:nth-child(6) {
      background: #000;
      opacity: 1;
    }
    
    
    /* Single */
    
    #sphere.single ul:nth-child(n+2) {
      opacity: 0;
    }
    
    
    /* Contact */
    
    #sphere.contact ul {
      opacity: 0;
    }
    
    #sphere.contact ul:nth-child(1),
    #sphere.contact ul:nth-child(4) {
      opacity: 0.8;
    }
    
    #sphere.contact .rotator {
      -webkit-animation: spinHorizontal 2s linear infinite;
      -moz-animation: spinHorizontal 2s linear infinite;
      animation: spinHorizontal 2s linear infinite;
    }
    
    #sphere.contact ul:nth-child(1) {
      -webkit-animation: spinVerticalReverse 5s linear infinite;
      -moz-animation: spinVerticalReverse 5s linear infinite;
      animation: spinVerticalReverse 5s linear infinite;
    }
    
    #sphere.contact ul:nth-child(4) {
      -webkit-animation: spinVertical 5s linear infinite;
      -moz-animation: spinVertical 5s linear infinite;
      animation: spinVertical 5s linear infinite;
    }
    
    .contact .rotator {
      -webkit-transition: -webkit-transform 500ms linear;
      -webkit-transform-style: preserve-3d;
      -moz-transition: -moz-transform 500ms linear;
      -moz-transform-style: preserve-3d;
      transition: transform 500ms linear;
      transform-style: preserve-3d;
    }
    
    
    /* Half */
    
    #sphere.half li {
      background: #000;
    }
    
    #sphere.half li:nth-child(n+12),
    #sphere.half ul:nth-child(n+4) li:nth-child(1) {
      display: none;
    }
    
    
    /* Animations */
    
    
    /*************************************************/
    
    @-webkit-keyframes spinHorizontal {
      from {
        -webkit-transform: rotateY(0deg);
      }
      to {
        -webkit-transform: rotateY(360deg);
      }
    }
    
    @-webkit-keyframes spinVertical {
      from {
        -webkit-transform: rotateX(0deg);
      }
      to {
        -webkit-transform: rotateX(360deg);
      }
    }
    
    @-webkit-keyframes spinVerticalReverse {
      from {
        -webkit-transform: rotateX(360deg);
      }
      to {
        -webkit-transform: rotateX(0deg);
      }
    }
    
    @-webkit-keyframes borderRadius {
      from {
        border-radius: 5px;
      }
      to {
        border-radius: 50px;
      }
    }
    
    @-moz-keyframes spinHorizontal {
      from {
        -moz-transform: rotateY(0deg);
      }
      to {
        -moz-transform: rotateY(360deg);
      }
    }
    
    @-moz-keyframes spinVertical {
      from {
        -moz-transform: rotateX(0deg);
      }
      to {
        -moz-transform: rotateX(360deg);
      }
    }
    
    @-moz-keyframes spinVerticalReverse {
      from {
        -moz-transform: rotateX(360deg);
      }
      to {
        -moz-transform: rotateX(0deg);
      }
    }
    
    @-moz-keyframes borderRadius {
      from {
        border-radius: 5px;
      }
      to {
        border-radius: 50px;
      }
    }
    
    @keyframes spinHorizontal {
      from {
        transform: rotateY(0deg);
      }
      to {
        transform: rotateY(360deg);
      }
    }
    
    @keyframes spinVertical {
      from {
        transform: rotateX(0deg);
      }
      to {
        transform: rotateX(360deg);
      }
    }
    
    @keyframes spinVerticalReverse {
      from {
        transform: rotateX(360deg);
      }
      to {
        transform: rotateX(0deg);
      }
    }
    
    @keyframes borderRadius {
      from {
        border-radius: 5px;
      }
      to {
        border-radius: 50px;
      }
    }
    
    .test p {
      text-align: center;
    }
    
    #controls {
      position: absolute;
      left: 48px;
      top: 48px;
    }
    
    #controls fieldset {
      border: 1px dotted #000;
      padding: 0.5em 1em 0 0.5em;
    }
    
    #controls label {
      font-weight: normal;
    }
    
    #controls div {
      margin: 0 0 0.5em;
    }
    
    #controls input {
      vertical-align: baseline;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <!-- Article: https://paulrhayes.com/2011-02/creating-a-sphere-with-3d-css/ -->
      <!-- Demo: https://paulrhayes.com/experiments/sphere/ -->
      <!-- Originally posted: 10th February 2011 -->
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
      <title>A sphere built with CSS 3D transforms &mdash; Paul Hayes</title>
      <meta name="author" content="Paul Hayes" />
      <link rel="canonical" href="https://paulrhayes.com/experiments/sphere/" />
      <link rel="stylesheet" href="../experiment-styles.css" />
    
      <link rel="stylesheet" href="css/experiment.css" />
    </head>
    
    <body class="experiment">
      <div class="wrapper">
    
        <div id="sphere" class="normal">
          <div class="rotator">
            <div class="container"></div>
          </div>
        </div>
        <p>Click and drag, use touch gestures or arrow keys.</p>
        <form id="controls" action="#">
          <fieldset>
            <legend class="strong">Sphere styles</legend>
            <div>
              <input id="normal" name="sphereType" type="radio" value="normal" checked />
              <label for="normal">Normal</label>
            </div>
            <div>
              <input id="square" name="sphereType" type="radio" value="square" />
              <label for="square">Square</label>
            </div>
            <div>
              <input id="eye" name="sphereType" type="radio" value="eye" />
              <label for="eye">Eye</label>
            </div>
            <div>
              <input id="half" name="sphereType" type="radio" value="half" />
              <label for="half">Half</label>
            </div>
            <div>
              <input id="single" name="sphereType" type="radio" value="single" />
              <label for="single">Single</label>
            </div>
            <div>
              <input id="contact" name="sphereType" type="radio" value="contact" />
              <label for="contact">Contact</label>
            </div>
            <div>
              <input id="kaleidoscope" name="sphereType" type="radio" value="kaleidoscope" />
              <label for="kaleidoscope">Kaleidoscope</label>
            </div>
          </fieldset>
        </form>
    
      </div>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
      <script src="js/experiment.js"></script>
    </body>
    
    </html>

    • 7
  3. Alexandr_TT
    2020-02-06T21:17:25Z2020-02-06T21:17:25Z

    下面的答案不是真正的 3D 形状。这只会产生轻微的 3D 错觉,但是,根据您的用例,您可以对其进行调整:

    html,body{margin:0;padding:0;background:#222;}
    div{
        height:300px;
        width:300px;
        background:url(http://lorempixel.com/300/300);
        border-radius:50%;
        animation:spin 3s linear infinite;
        transform:rotate(-15deg);
        position:relative;
    }
    div:before{
        content:"";
        position:absolute;
        bottom:-50px;
        border-radius:50%;
        left:0;
        height:10%;
        width:100%;
        transform:rotate(15deg);
        background:rgba(0,0,0,0.6);
        box-shadow: 0 0 10px 2px rgba(0,0,0,0.6);
        
    }
    div:after{
        content:"";
        position:absolute;z-index:12;
        top:0;left:0;height:100%;width:100%;border-radius:50%;
    box-shadow:inset -20px -20px 20px 2px #222, inset 20px 20px 20px 5px rgba(200,200,200,0.4);    
    }
    @keyframes spin{
        to{background-position:-300px 0;}
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    <div></div>

    background-position通过为div设置动画并使用 shadows box shadows,您可以“模拟” 3D 形状的阴影。

    • 6
  4. Alexandr_TT
    2020-02-06T21:26:57Z2020-02-06T21:26:57Z

    JS解决方案

    我JavaScript用来构建一个由许多元素组成的球体div。为了保持浏览器性能,div 元素尽可能小。

    var DIAMETER = 200;
    var CELLS_PER_CIRCLE = 26;
    var IMG_CELL = 'https://sites.google.com/site/zulnasibu/sphere/earth.png';
    var NAME = 'sphere';
    var WRAP = NAME + '-wrapper';
    var _cssRules = '';
    var _cellW;
    var _cellAmount = 0;
    var _imgW;
    var _imgH;
    
    function createFace(w, h, rx, ry, tz, ts, tsx, tsy, cname) {
    	var face = document.createElement("div");
    	var css;
    	var cssText =
    		'width: ' + w.toFixed(2) + 'px;' +
    		'height: ' + h.toFixed(2) + 'px;' +
    		'margin-left: ' + (-w / 2).toFixed(2) + 'px;' +
    		'margin-top: ' + (-h / 2).toFixed(2) + 'px;' +
    		'background: url("' + ts + '") ' + tsx.toFixed(2) + 'px ' + tsy.toFixed(2) + 'px;';
    	css = 'transform: rotateY(' + ry.toFixed(2) + 'rad) rotateX(' + rx.toFixed(2) + 'rad) translateZ(' + tz.toFixed(2) + 'px);';
    	cssText += addVendorPrefix(css);
    	face.className = cname;
    	face.style.cssText = cssText;
    	return face;
    }
    
    function createModel() {
    	var wrap = document.createElement("div");
    	var model = document.createElement("div");
    	wrap.className = WRAP;
    	model.className = NAME;
    	if (CELLS_PER_CIRCLE % 2 != 0) CELLS_PER_CIRCLE++;
    	if (CELLS_PER_CIRCLE < 4) CELLS_PER_CIRCLE = 4;
    	var baseAngle = Math.PI / CELLS_PER_CIRCLE;
    	var cellAngle = 2 * baseAngle;
    	_cellW = DIAMETER * Math.tan(baseAngle);
    	_imgW = _cellW * CELLS_PER_CIRCLE;
    	_imgH = CELLS_PER_CIRCLE / 2;
    	if (CELLS_PER_CIRCLE % 4 == 0) _imgH++;
    	_imgH *= _cellW;
    	var xc = Math.ceil(CELLS_PER_CIRCLE / -4);
    	var yc, rx, ry, tx, ty = -_imgH, tw, cang, cdia, cw;
    	for (var x = xc; x <= -xc; x++) {
    		rx = x * cellAngle;
    		cw = _cellW;
    		yc = CELLS_PER_CIRCLE;
    		if (Math.abs(rx) == Math.PI / 2)
    			yc = 1;
    		else if (Math.abs(x) != 1) {
    			cang = rx - Math.sign(x) * cellAngle / 2;
    			cdia = DIAMETER * Math.cos(cang);
    			cw = cdia * Math.tan(baseAngle);
    		}
    		_cellAmount += yc;
    		tw = cw * yc;
    		tx = (tw - _imgW) / 2;
    		ty += _cellW;
    		for (var y = 0; y < yc; y++) {
    			ry = y * cellAngle;
    			model.appendChild(createFace(cw + 1, _cellW + 1, rx, ry, DIAMETER / 2, IMG_CELL, tx, ty, 'cell' + x.toString() + y.toString()));
    			tx -= cw;
    		}
    	}
    	wrap.appendChild(model);
    	var style = document.createElement('style');
    	style.type = 'text/css';
    	if (style.styleSheet)
    		style.styleSheet.cssText = _cssRules;
    	else
    		style.innerHTML = _cssRules;
    	document.head.appendChild(style);
    	return wrap;
    }
    
    function addVendorPrefix(property) {
    	return	'-webkit-' + property +
    			'-moz-' + property +
    			'-o-' + property +
    			property;
    }
    
    function showGeometry(elm) {
    	if (elm.checked)
    		document.querySelector('.sphere').classList.add('show-geometry');
    	else
    		document.querySelector('.sphere').classList.remove('show-geometry');
    }
    
    document.body.appendChild(createModel());
    .sphere-wrapper {
    	position: absolute;
    	top: 50%;
    	left: 50%;
    	-webkit-perspective: 1000px;
    	-moz-perspective: 1000px;
    	-o-perspective: 1000px;
    	perspective: 1000px;
    }
    .sphere {
    	position: absolute;
    	-webkit-transform-style: preserve-3d;
    	-moz-transform-style: preserve-3d;
    	-o-transform-style: preserve-3d;
    	transform-style: preserve-3d;
    	-webkit-transform-origin: center center -100px;
    	-moz-transform-origin: center center -100px;
    	-o-transform-origin: center center -100px;
    	transform-origin: center center -100px;
    	-webkit-animation: spin 60s infinite linear;
    	-moz-animation: spin 60s infinite linear;
    	-o-animation: spin 60s infinite linear;
    	animation: spin 60s infinite linear;
    }
    .sphere div {
    	position: absolute;
    	-webkit-backface-visibility: hidden;
    	-moz-backface-visibility: hidden;
    	-o-backface-visibility: hidden;
    	backface-visibility: hidden;
    }
    @-webkit-keyframes spin {
    	010.00% {-webkit-transform: rotateX(   0deg) rotateY( 360deg) rotateZ(   0deg);}
    	020.00% {-webkit-transform: rotateX( 360deg) rotateY( 360deg) rotateZ(   0deg);}
    	030.00% {-webkit-transform: rotateX( 720deg) rotateY( 720deg) rotateZ(   0deg);}
    	100.00% {-webkit-transform: rotateX(2880deg) rotateY(3240deg) rotateZ(2520deg);}
    }
    @-moz-keyframes spin {
    	010.00% {-moz-transform: rotateX(   0deg) rotateY( 360deg) rotateZ(   0deg);}
    	020.00% {-moz-transform: rotateX( 360deg) rotateY( 360deg) rotateZ(   0deg);}
    	030.00% {-moz-transform: rotateX( 720deg) rotateY( 720deg) rotateZ(   0deg);}
    	100.00% {-moz-transform: rotateX(2880deg) rotateY(3240deg) rotateZ(2520deg);}
    }
    @-o-keyframes spin {
    	010.00% {-o-transform: rotateX(   0deg) rotateY( 360deg) rotateZ(   0deg);}
    	020.00% {-o-transform: rotateX( 360deg) rotateY( 360deg) rotateZ(   0deg);}
    	030.00% {-o-transform: rotateX( 720deg) rotateY( 720deg) rotateZ(   0deg);}
    	100.00% {-o-transform: rotateX(2880deg) rotateY(3240deg) rotateZ(2520deg);}
    }
    @keyframes spin {
    	010.00% {transform: rotateX(   0deg) rotateY( 360deg) rotateZ(   0deg);}
    	020.00% {transform: rotateX( 360deg) rotateY( 360deg) rotateZ(   0deg);}
    	030.00% {transform: rotateX( 720deg) rotateY( 720deg) rotateZ(   0deg);}
    	100.00% {transform: rotateX(2880deg) rotateY(3240deg) rotateZ(2520deg);}
    }
    input, input~ label {
    	cursor: pointer;
    }
    input:checked~ label {
    	color: #f77;
    }
    .show-geometry div {
    	background: rgba(160, 160, 160, 0.5) !important;
    	border: 1px solid #333;
    	-webkit-backface-visibility: visible;
    	-moz-backface-visibility: visible;
    	-o-backface-visibility: visible;
    	backface-visibility: visible;
    }
    <input id="show-geometry" type="checkbox" onchange="showGeometry(this);">
    <label for="show-geometry">Show geometry</label>

    答案来源: @ZulNs

    • 6

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5