3d-earth
<!doctyle html>
<html>
<head>
<style>
.box>div {  
  position: absolute;  
  width: 50px;  
  height: 50px;  
  border-radius: 50%;  
  background: rgba(255, 0, 0, .6);
}
.container,.box { 
      position: relative;  
    width: 100%;  
    height: 100%;  
    display: flex;  
   justify-content: center;  
   align-items: center;  
  transform-style: preserve-3d;
}
.container {  
  perspective: 500px;  
  overflow: hidden;
}
.box {  
  animation: rotate 20s linear infinite;
}
.box>div {  
  position: absolute;  
  width: 320px;  
  height: 320px;  
  border: solid 1px #000;  border-radius: 50%;
}
@keyframes rotate { 
  0% { transform: rotateZ(23deg) rotateY(0deg); }
100% { transform: rotateZ(23deg) rotateY(360deg); }}
</style>
 
<script>
function addLongitude() {  
  var count = 18  
  var stepDeg = 180 / count  
  var fragment = document.createDocumentFragment()  
  for (var i = 0; i < count; i++) {    
    var div = document.createElement('div')    
    div.style.transform = 'rotateY(' + ~~(i * stepDeg) + 'deg)'    
    fragment.appendChild(div)  
  }  
  document.querySelector('.box').appendChild(fragment)}
  function addLatitude() {  
    var r = 160  
    var stepDeg = 10  
    var start = -80  
    var end = 80  
    var fragment = document.createDocumentFragment() 
    for (var i = start; i <= end; i += stepDeg) {    
      var div = document.createElement('div')   
      var _r = ~~(Math.cos(i / 180 * Math.PI) * r * 2) + 'px'    
      div.style.width = _r    
      div.style.height = _r    
      div.style.transform = 'translateY(' + ~~(Math.sin(i / 180 * Math.PI) * r) + 'px) rotateX(90deg)'    
      fragment.appendChild(div) 
    }  
    document.querySelector('.box').appendChild(fragment)}
    window.onload = function () {  
      addLongitude()  
      addLatitude()
    }
function draw(deg) {  
  var fragment = document.createDocumentFragment() 
  var r = 180 // 赤道半径  
  r *= Math.cos(deg * Math.PI * 2 / 360) // 对应纬度 圆半径  
  var size = 46 // 填充圆直径  
  var len = r * 2 * Math.PI / size  
  for (var i = 0; i < len; i++) {    
    var div = document.createElement('div')    
    div.style.transform = 'rotateY(' + ~~(360 / len * i) + 'deg) rotateX(' + deg + 'deg) translateZ(160px)'    
    fragment.appendChild(div) 
  }
  document.querySelector('.box').appendChild(fragment)
}
window.onload = function () {  
  for (var i = -90; i <= 90; i += 20) {   
    draw(i)  
  }
}
div.style.backgroundPosition = (100 * i / len) + '% -' + (deg + 90) / 180 * 100 + '%'
</script>
</head>
<body>
<div class="container">  <div class="box"> </div></div>
</body>
</html>