How to create a sphere in css?

左心房为你撑大大i 提交于 2019-11-30 07:14:05

The below answer is not an actual 3D shape. It only gives a slight illusion of being 3D, however, depending on your use case, you may be able to 'fake' it:

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>

It's animating the background-position of the div, and by using box shadows, you could 'mimic' the shadowing of a 3D shape.

You might want to use 3D rotated circles:

This uses rotated circles to look like a spherical grid. the lesser no. of elements, the better performance.

Some elements have been rotated in X axis, and others in Y axis. I have filled different colours to show this:

#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>

You can also rotate some elements in Z direction, but that will make it even more buggy. Now if you fill the same colours in circles, it almost looks like a sphere:

#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>

I use JavaScript to build the sphere which formed by many div elements. To maintain the browser performance, the div elements are made as little as possible.

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>
Persijn

Sphere like shape

There is no actual 3D shapes in html5
But you can stack 2D shapes on top of each other.
With this in mind you can create pretty a close representation of a sphere.

.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>

#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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!