JSFiddle - React, Tailwind, and code Playground
by Felis Catus
HTML
Click padlock to unlock/relock!
<div class="container">
<div class="spinner">
<svg width="100%" height="100%" viewBox="-1 -1 202 202">
<!--circle id="spinarch" cx="100" cy="100" r="99" style="stroke:red; fill:none; stroke-width:2"/-->
<path id="spinarch" d="M 1,100" style="fill:none"/>
</svg>
</div>
<div class="lockback">
<div class="padlock">
<div class="shackle">
<div class="inside"></div>
</div>
<div class="lock">
</div>
<div class="patch">
</div>
</div>
</div>
</div>
CSS
/*colors*/
#spinarch{
stroke:#3fb1e5;
stroke-width:2;
}
.container{
background:transparent;
}
.lockback, .shackle>.inside, .patch{
background:#3fb1e5;
}
.lock{
border-color:#3fb1e5;
}
.shackle, .lock{
background:white;
}
/*for example only. container has to be square.*/
body{
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)),url("http://www.traipse.com/penrose_tiles/penrose_tiles.gif");
}
.container{
width:100px;
height:100px;
margin:100px 100px;
}
/*structure - don't touch*/
.container{
position:relative;
overflow:hidden;
}
.spinner{
position:absolute;
background:inherit;
width:100%;
height:100%;
margin:50% 0 0 50%;
top:-50%;
left:-50%;
transform:rotate(0deg);
-webkit-transform:rotate(0deg);
border-radius:50%;
}
.lockback{
position:absolute;
width:88%;
height:88%;
margin:50% 0 0 50%;
top:-44%;
left:-44%;
border-radius:50%;
overflow:hidden;
transition:transform 250ms linear;
-webkit-transition:-webkit-transform 250ms linear;
}
.padlock{
position:absolute;
width:36%;
height:56%;
margin:50% 0 0 50%;
top:-28%;
left:-18%;
}
.shackle{
border-radius:50% 50% 0% 0%/50% 50% 0% 0%;
width:76%;
height:45%;
left:12%;
position:relative;
transform-origin:4% 0;
-webkit-transform-origin:4% 0;
transition:transform 250ms linear;
-webkit-transition:-webkit-transform 500ms linear;
}
.lock{
border-radius:12%/20%;
width:100%;
height:45%;
position:relative;
border-width:2px;
border-style:solid;
left:-2px;
}
.shackle>.inside{
width:80%;
height:92%;
top:10%;
left:10%;
position:absolute;
border-radius:50% 50% 0% 0%/50% 50% 0% 0%;
}
.patch{
width:90%;
height:17%;
position:absolute;
top:30%;
left:-81%;
}
JavaScript
(function setEvents(){
var clicked=0;
var intId=0;
var int2Id=0;
var aperture=0;
var angle=0;
var dAperture=10;
var transformFunc=((/^((?!chrome).)*safari/i.test(navigator.userAgent))?"-webkit-transform":"transform");
var shackle=document.getElementsByClassName("shackle")[0];
var arc=document.getElementById("spinarch");
var spinner=document.getElementsByClassName("spinner")[0];
function setAperture(ang){
ang%=360;
var ex=100+Math.round(100*Math.cos(6.28318531*ang/360.0));
var ey=100+Math.round(100*Math.sin(6.28318531*ang/360.0));
if(ang<=90){
arc.setAttribute("d","M 200,100 A 100,100 0 0,1 "+ex+","+ey);
}else if(ang<=180){
arc.setAttribute("d","M 200,100 A 100,100 0 0,1 100,200 A 100,100 0 0,1 "+ex+","+ey);
}else if(ang<=270){
arc.setAttribute("d","M 200,100 A 100,100 0 0,1 100,200 A 100,100 0 0,1 0,100 A 100,100 0 0,1 "+ex+","+ey);
}else{
arc.setAttribute("d","M 200,100 A 100,100 0 0,1 100,200 A 100,100 0 0,1 0,100 A 100,100 0 0,1 100,0 A 100,100 0 0,1 "+ex+","+ey);
}
}
document.getElementsByClassName("lockback")[0].onclick=function padlockClick(evt){
if(clicked){
clicked=0;
shackle.style[transformFunc]="";
clearInterval(intId);
setAperture(0);
clearInterval(int2Id);
}else{
clicked=1;
shackle.style[transformFunc]="rotateY(180deg)";
intId=setInterval(function(){
if(aperture<=0){
aperture=0;
dAperture=-dAperture;
}else if(aperture>300){
dAperture=-dAperture;
}
setAperture(aperture);
aperture=(aperture+dAperture)%360;
},50);
int2Id=setInterval(function(){
spinner.style[transformFunc]="rotate("+angle+"deg)";
angle=(angle+20)%360;
},50);
}
}
}());