【问题标题】:How to create a sphere in css?如何在css中创建一个球体?
【发布时间】:2015-09-02 16:57:42
【问题描述】:

我试图仅使用纯 css 创建一个 3D 球体,但我无法生成所需的形状。我见过cylinder,但我找不到任何关于创建实际 sphere 的参考。

我当前的代码如下:

.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 中旋转它们(我想要旋转图像)。

对不起,如果我错过了什么,但我不太确定我应该去哪里问这个。

【问题讨论】:

  • I can't find any reference to creating an actual sphere. Really?
  • 您可能想从较小的东西开始。你试过先做一个立方体吗?为此创建一个 Sphere 需要一些时间。或者,yo9u 可以看看this

标签: html css css-shapes css-transforms shapes


【解决方案1】:

#cont {
  perspective: 10000px;
  transform-style: preserve-3d;
  -webkit-animation: rotat 1s linear infinite;
  animation: rotat 10s linear infinite;
  transform-origin: 50% 50% 50%;
}
.circ {
  height: 200px;
  width: 200px;
  border: 2px solid black;
  border-radius: 50%;
  position: absolute;
  top: 50px;
  left: 50%;
  margin-left: -100px;
  transform-origin: 50%;
  transform-style: preserve-3d;
  background: orange;
}
.circ:nth-child(1) {
  transform: rotateX(0deg);
}
.circ:nth-child(2) {
  transform: rotateX(30deg);
}
.circ:nth-child(3) {
  transform: rotateX(60deg);
}
.circ:nth-child(4) {
  transform: rotateX(90deg);
}
.circ:nth-child(5) {
  transform: rotateX(120deg);
}
.circ:nth-child(6) {
  transform: rotateX(150deg);
}
.circ:nth-child(7) {
  transform: rotateX(180deg);
}
/*other side rotated*/

.circ:nth-child(8) {
  transform: rotateY(30deg);
}
.circ:nth-child(9) {
  transform: rotateY(60deg);
}
.circ:nth-child(10) {
  transform: rotateY(90deg);
}
.circ:nth-child(11) {
  transform: rotateY(120deg);
}
.circ:nth-child(12) {
  transform: rotateY(150deg);
}
.circ:nth-child(13) {
  transform: rotateY(180deg);
}
.oth {
  background: crimson;
}
@-webkit-keyframes rotat {
  0% {
    -webkit-transform: rotateY(0deg) translateX(0);
  }
  100% {
    -webkit-transform: rotateY(360deg);
  }
}
@keyframes rotat {
  0% {
    transform: rotateY(0deg);
  }
  100% {
    transform: rotateY(360deg);
  }
}
<div id="cont">
  <div class="circ"></div>
  <div class="circ"></div>
  <div class="circ"></div>
  <div class="circ"></div>
  <div class="circ"></div>
  <div class="circ"></div>
  <div class="circ"></div>
  <!--rotated other side-->
  <div class="circ oth"></div>
  <div class="circ oth"></div>
  <div class="circ oth"></div>
  <div class="circ oth"></div>
  <div class="circ oth"></div>
  <div class="circ oth"></div>
</div>

【讨论】:

    【解决方案2】:

    我使用 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>

    【讨论】:

      【解决方案3】:

      以下答案不是实际的 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>

      它为 div 的 background-position 设置动画,通过使用盒子阴影,您可以“模仿”3D 形状的阴影。

      【讨论】:

      • 这看起来很有希望。谢谢!
      • 我用这个搞定了!不过,我不喜欢链接中的许多元素!
      【解决方案4】:

      您可能想要使用 3D 旋转圆

      这使用旋转的圆圈看起来像一个球形网格。较小的没有。元素,性能更好。

      一些元素在 X 轴上旋转,而另一些在 Y 轴上旋转。我填充了不同的颜色来显示这个:

      #cont {
        perspective: 10000px;
        transform-style: preserve-3d;
        -webkit-animation: rotat 1s linear infinite;
        animation: rotat 10s linear infinite;
        transform-origin: 50% 50% 50%;
      }
      .circ {
        height: 200px;
        width: 200px;
        border: 2px solid black;
        border-radius: 50%;
        position: absolute;
        top: 50px;
        left: 50%;
        margin-left: -100px;
        transform-origin: 50%;
        transform-style: preserve-3d;
        background: orange;
      }
      .circ:nth-child(1) {
        transform: rotateX(0deg);
      }
      .circ:nth-child(2) {
        transform: rotateX(30deg);
      }
      .circ:nth-child(3) {
        transform: rotateX(60deg);
      }
      .circ:nth-child(4) {
        transform: rotateX(90deg);
      }
      .circ:nth-child(5) {
        transform: rotateX(120deg);
      }
      .circ:nth-child(6) {
        transform: rotateX(150deg);
      }
      .circ:nth-child(7) {
        transform: rotateX(180deg);
      }
      /*other side rotated*/
      
      .circ:nth-child(8) {
        transform: rotateY(30deg);
      }
      .circ:nth-child(9) {
        transform: rotateY(60deg);
      }
      .circ:nth-child(10) {
        transform: rotateY(90deg);
      }
      .circ:nth-child(11) {
        transform: rotateY(120deg);
      }
      .circ:nth-child(12) {
        transform: rotateY(150deg);
      }
      .circ:nth-child(13) {
        transform: rotateY(180deg);
      }
      .oth {
        background: crimson;
      }
      @-webkit-keyframes rotat {
        0% {
          -webkit-transform: rotateY(0deg) translateX(0);
        }
        100% {
          -webkit-transform: rotateY(360deg);
        }
      }
      @keyframes rotat {
        0% {
          transform: rotateY(0deg);
        }
        100% {
          transform: rotateY(360deg);
        }
      }
      <div id="cont">
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <!--rotated other side-->
        <div class="circ oth"></div>
        <div class="circ oth"></div>
        <div class="circ oth"></div>
        <div class="circ oth"></div>
        <div class="circ oth"></div>
        <div class="circ oth"></div>
      </div>

      您还可以在 Z 方向旋转一些元素,但这会使其更加错误。现在如果你用相同的颜色填充圆圈,它看起来就像一个球体

      #cont {
        perspective: 10000px;
        transform-style: preserve-3d;
        -webkit-animation: rotat 1s linear infinite;
        animation: rotat 10s linear infinite;
        transform-origin: 50% 50% 50%;
      }
      .circ {
        height: 200px;
        width: 200px;
        border: 2px solid black;
        border-radius: 50%;
        position: absolute;
        top: 50px;
        left: 50%;
        margin-left: -100px;
        transform-origin: 50%;
        transform-style: preserve-3d;
        background: crimson;
      }
      .circ:nth-child(1) {
        transform: rotateX(0deg);
      }
      .circ:nth-child(2) {
        transform: rotateX(30deg);
      }
      .circ:nth-child(3) {
        transform: rotateX(60deg);
      }
      .circ:nth-child(4) {
        transform: rotateX(90deg);
      }
      .circ:nth-child(5) {
        transform: rotateX(120deg);
      }
      .circ:nth-child(6) {
        transform: rotateX(150deg);
      }
      .circ:nth-child(7) {
        transform: rotateX(180deg);
      }
      /*other side rotated*/
      
      .circ:nth-child(8) {
        transform: rotateY(30deg);
      }
      .circ:nth-child(9) {
        transform: rotateY(60deg);
      }
      .circ:nth-child(10) {
        transform: rotateY(90deg);
      }
      .circ:nth-child(11) {
        transform: rotateY(120deg);
      }
      .circ:nth-child(12) {
        transform: rotateY(150deg);
      }
      .circ:nth-child(13) {
        transform: rotateY(180deg);
      }
      .o {
        border: none;
      }
      @-webkit-keyframes rotat {
        0% {
          -webkit-transform: rotateY(0deg);
        }
        100% {
          -webkit-transform: rotateY(360deg);
        }
      }
      @keyframes rotat {
        0% {
          transform: rotateY(0deg);
        }
        100% {
          transform: rotateY(360deg);
        }
      }
      <div id="cont">
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <div class="circ"></div>
        <!--rotated other side-->
        <div class="circ o"></div>
        <div class="circ o"></div>
        <div class="circ o"></div>
        <div class="circ o"></div>
        <div class="circ o"></div>
        <div class="circ o"></div>
      </div>

      【讨论】:

        【解决方案5】:

        球形

        html5 中没有实际的 3D 形状
        但是您可以将 2D 形状堆叠在一起。
        考虑到这一点,您可以创建非常接近的球体表示。

        .container {
          perspective: 1000px;
          //transform-style: preserve-3d;
          width: 300px;
          height: 300px;
          border: 5px solid pink;
        }
        .circ {
          transform-style: preserve-3d;
          border: 5px solid firebrick;
          border-radius: 50%;
          position: absolute;
          top: 50%;
          left: 50%;
          transform-origin: center;
          transform: translateX(-50%) translateY(-50%);
          transition: transform 2s linear;
        }
        .circ:nth-of-type(1) {
          height: 10%;
          width: 10%;
          transform: translateX(-50%) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(-55px);
        }
        .circ:nth-of-type(2) {
          height: 20%;
          width: 20%;
          transform: translatex(-50%) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(-45px);
        }
        .circ:nth-of-type(3) {
          height: 30%;
          width: 30%;
          transform: translatex(-50%) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(-25px);
        }
        .circ:nth-of-type(4) {
          height: 40%;
          width: 40%;
          transform: translatex(-50%) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(-10px);
        }
        .circ:nth-of-type(5) {
          height: 40%;
          width: 40%;
          transform: translatex(-50%) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(10px);
        }
        .circ:nth-of-type(6) {
          height: 30%;
          width: 30%;
          transform: translatex(-50%) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(25px);
        }
        .circ:nth-of-type(7) {
          height: 20%;
          width: 20%;
          transform: translatex(-50%) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(45px);
        }
        .circ:nth-of-type(8) {
          height: 10%;
          width: 10%;
          transform: translatex(calc(-50%)) translateY(-50%) rotateX(40deg) rotateY(40deg) translateZ(55px);
        }
        /*ANIMATION*/
        
        .container:hover .circ:nth-of-type(1) {
          transform: translateX(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(-60px);
        }
        .container:hover .circ:nth-of-type(2) {
          transform: translatex(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(-40px);
        }
        .container:hover .circ:nth-of-type(3) {
          transform: translatex(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(-20px);
        }
        .container:hover .circ:nth-of-type(4) {
          transform: translatex(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(0px);
        }
        .container:hover .circ:nth-of-type(5) {
          transform: translatex(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(20px);
        }
        .container:hover .circ:nth-of-type(6) {
          transform: translatex(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(40px);
        }
        .container:hover .circ:nth-of-type(7) {
          transform: translatex(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(60px);
        }
        .container:hover .circ:nth-of-type(8) {
          transform: translatex(-50%) translateY(-50%) rotateX(180deg) rotateY(40deg) translateZ(70px);
        }
        .container:hover {
          background-color: #f2f2f2;
        }
        <div class="container">
          <div class="circ"></div>
          <div class="circ"></div>
          <div class="circ"></div>
          <div class="circ"></div>
          <div class="circ"></div>
          <div class="circ"></div>
          <div class="circ"></div>
          <div class="circ"></div>
        </div>

        【讨论】:

        • 非常好!如果你使用三角比来生成它,它会更加真实!
        猜你喜欢
        • 1970-01-01
        • 2017-12-27
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-24
        • 2020-07-19
        • 2014-09-03
        相关资源
        最近更新 更多