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>