JSFiddle - React, Tailwind, and code Playground
HTML
<div id="pixels1" class="pixels"></div>
<div id="size"></div>
opacity <input id="opacity" type="range" min="0" max="1" step=".01" value=".5">
CSS
html,body{width:100%;height:100%;margin:0;padding:0;}
.pixels{
background-color:hsla(0,0%,0%,0);
/*transform:scale(.5);*/
top:50%;
left:50%;
position:fixed;
}
.pixels>div{
width:50px;
height:50px;
position:absolute;
top:-25px;
left:-25px;
background-image:url(http://i.imgur.com/1SFXtTl.jpg);
background-size:contain;
box-shadow:0 0 4px 0 hsla(0,0%,0%,.3);
}
.pixels>div>div{
width:34px;
height:34px;
padding:0;
margin:8px;
position:absolute;
border-radius:50%;
}
#size{
position:fixed;
bottom:20px;
left:20px;
border:2px solid black;
border-top:none;
text-align:center;
line-height:16px;
width:94px;
}
JavaScript
var shift=0,
scale=1,
pixels=60,
radius=pixels*7/Math.PI/2*10,
duration=6000,
start=Date.now(),
opacity=.5,
now,
board=document.getElementById('pixels1');
document.getElementById('opacity').addEventListener('input',function(){opacity=this.value},false);
window.onresize=function(){
var scaled='scale('+Math.min(window.innerHeight,window.innerWidth)/(radius*2+100)+')';
document.getElementById('size').style.transform=board.style.transform=scaled;
};
for(var i=0;i<pixels;i++){
board.appendChild(document.createElement('div')).appendChild(document.createElement('div'));
board.childNodes[i].style.transformOrigin='50% 50%';
board.childNodes[i].style.transform='rotate('+360/pixels*i+'deg) translateX(-'+radius+'px)';
}
var scaled='scale('+Math.min(window.innerHeight,window.innerWidth)/(radius*2+100)+')';
document.getElementById('size').style.transformOrigin='0% 100%';
document.getElementById('size').style.transform=board.style.transform=scaled;
document.getElementById('size').textContent='1cm';
function A(){
now=Date.now()-start;
for(var i=0;i<pixels;i++){
var scaled=pixels*scale,color='hsla('+(((360/scaled*i)+shift)%360)+',100%,50%,'+opacity+')';
board.childNodes[i].firstChild.style.backgroundColor=color;
board.childNodes[i].firstChild.style['box-shadow']='0 0 '+(48*opacity|0)+'px '+(16*opacity|0)+'px '+color;
}
shift=(now/duration*360|0)%360;
if(now>duration){start=Date.now()};
}
setTimeout(function(){
window.setInterval(A,16);
},3000);