First steps, need to sort out perspective stuff with the lights.
A Pen by Mario Nebl on CodePen.
<nav class="toolbar"> | |
<label class="trigger" for="animationstate">Toggle animation</label> | |
<label class="trigger" for="gutterstate">Toggle plain gutter</label> | |
</nav> | |
<input type="checkbox" class="state animationstate" id="animationstate" /> | |
<input type="checkbox" class="state gutterstate" id="gutterstate" /> | |
<div class="camera"> | |
<div class="scene"> | |
<figure class="pyramid"> | |
<div class="base"></div> | |
<div class="face"></div> | |
<div class="face"></div> | |
<div class="face"></div> | |
<div class="face"></div> | |
</figure> | |
<div class="light"> | |
<div class="incoming"></div> | |
<div class="outgoing"></div> | |
</div> | |
</div> | |
</div> |
var sceneEl = document.querySelectorAll('.scene')[0]; | |
var sceneTransform = { | |
x: 90, | |
y: 0, | |
dirty: false | |
}; | |
var moveScene = function(){ | |
if (! sceneTransform.dirty) { | |
return requestAnimationFrame(moveScene); | |
} | |
sceneEl.style.transform = 'rotateX('+ sceneTransform.x + 'deg) rotateY('+ sceneTransform.y +'deg)'; | |
sceneTransform.dirty = false; | |
requestAnimationFrame(moveScene); | |
} | |
requestAnimationFrame(moveScene); | |
var setScene = function(x, y) { | |
y = y || 0; | |
sceneTransform.x = sceneTransform.x + x; | |
sceneTransform.y = sceneTransform.y + y; | |
sceneTransform.dirty = true; | |
} | |
document.addEventListener('keydown', function(e){ | |
switch(e.keyCode){ | |
case 38: // up | |
case 87: // w | |
setScene(1, 0); | |
break; | |
case 39: // right | |
case 68: // d | |
setScene(0, 1); | |
break; | |
case 40: // down | |
case 83: // s | |
setScene(-1, 0); | |
break; | |
case 37: // left | |
case 65: // a | |
setScene(0, -1); | |
break; | |
} | |
}, false); |
@b:20rem; | |
@h:20rem; | |
@sceneTransform: rotateX(90deg); | |
@gutterTransform: translateZ(-100px); | |
@borderWidth:.2rem; | |
@borderColor:#b7d4da; | |
@a:sqrt(@b/2 * @b/2 + @h*@h); | |
@aRel:sqrt(@a/@b); | |
@bRel:sqrt(@b/@a); | |
@sideLength:sqrt(@b/2 * @b/2 + @h*@h); | |
@sideDeg:asin(@b/1.95 / @sideLength); | |
@closeDeg:120deg; // todo: calculate | |
@skewOffset:75%; | |
@secondSideTransform: translate3d(-@b/2, -@b/@h*50%, 0) rotate(90deg); | |
@thirdSideTransform: translate3d(0%, -@b, 0) rotate(180deg); | |
@fourthSideTransform: translate3d(@b/2, -@b/@h*50%, 0) rotate(-90deg); | |
@keyframes rotate{ | |
0% { | |
transform: rotate(0); | |
} | |
100% { | |
transform: rotate(360deg); | |
} | |
} | |
@keyframes discodisco{ | |
0% { | |
filter: saturate(1); | |
} | |
50% { | |
filter: saturate(0.1); | |
} | |
} | |
@keyframes pulse{ | |
0% { | |
opacity: 1; | |
} | |
50% { | |
opacity: .3; | |
} | |
} | |
@keyframes shine{ | |
0% { | |
transform: skewX(-75deg) scaleX(0); | |
} | |
100% { | |
transform: skewX(-75deg) scaleX(1); | |
} | |
} | |
@keyframes break{ | |
0% { | |
transform: skewX((360deg - @closeDeg - 30deg)*-1) skewY(-17deg) translateY(100px) translateX(100px) scaleX(0); | |
} | |
100% { | |
transform: skewX((360deg - @closeDeg - 30deg)*-1) skewY(-17deg) translateY(100px) translateX(100px) scaleX(1); | |
} | |
} | |
*{ | |
box-sizing: border-box; | |
} | |
figure{ | |
margin: 0; | |
} | |
html,body{ | |
margin: 0; | |
padding: 0; | |
height: 100%; | |
background: #000; | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
font-size: 10px; | |
color: #fff; | |
width: 100%; | |
overflow: hidden; | |
} | |
.toolbar{ | |
position: fixed; | |
width: 100%; | |
z-index: 10; | |
padding: 5px; | |
background: rgba(255,255,255,.4); | |
} | |
.trigger{ | |
display: inline-block; | |
font-size: 1.3rem; | |
padding: 5px 10px; | |
&:hover, | |
&:active{ | |
background: rgba(0,0,0,.3); | |
transition: .3s background ease-in; | |
} | |
} | |
.state{ | |
position: absolute; | |
top: 0; | |
left: -100vw; | |
} | |
.camera{ | |
display: flex; | |
align-items: center; | |
height: 100%; | |
persepective: 1000px; | |
} | |
.scene{ | |
flex-grow: 1; | |
text-align: center; | |
transform: @sceneTransform; | |
transform-style: preserve-3d; | |
animation-play-state: paused; | |
&::before{ | |
content: ''; | |
opacity: 0; | |
position: absolute; | |
top: -500vh; | |
left: -500vw; | |
display: block; | |
height: 1000vh; | |
width: 1000vw; | |
transition: .3s opacity ease-in; | |
transform: @gutterTransform; | |
background-image: linear-gradient(fadeout(#fff, 50%) 2px, transparent 2px), | |
linear-gradient(90deg, fadeout(#fff, 50%) 2px, transparent 2px), | |
linear-gradient(fadeout(#fff, 70%) 1px, transparent 1px), | |
linear-gradient(90deg, fadeout(#fff, 70%) 1px, transparent 1px); | |
background-size:100px 100px, 100px 100px, 20px 20px, 20px 20px; | |
background-position:-2px -2px, -2px -2px, -1px -1px, -1px -1px; | |
} | |
} | |
.pyramid{ | |
display: inline-block; | |
animation-play-state: inherit; | |
transform-style: preserve-3d; | |
} | |
.base,.face{ | |
transform-origin: 50% 0; | |
transition: .3s transform ease-in; | |
} | |
.base{ | |
content: '@{sideDeg}'; | |
width: @b; | |
height: @b; | |
border: @borderWidth solid @borderColor; | |
box-shadow: inset 0 0 1rem fadeout(@borderColor, 90%), 0 0 1rem fadeout(@borderColor, 90%); | |
} | |
.face{ | |
position: absolute; | |
z-index:1; | |
width: @b; | |
height: @h; | |
-webkit-clip-path: polygon(100/3% 0, 50% 100%, 100*2/3% 0); | |
-moz-clip-path: polygon(100/3% 0, 50% 100%, 100*2/3% 0); | |
-ms-clip-path: polygon(100/3% 0, 50% 100%, 100*2/3% 0); | |
clip-path: polygon(100/3% 0, 50% 100%, 100*2/3% 0); | |
border-top: @borderWidth solid @borderColor; | |
&:nth-child(2){ | |
transform: rotateX(@closeDeg); | |
} | |
&:nth-child(3){ | |
transform: @secondSideTransform rotateX(@closeDeg); | |
} | |
&:nth-child(4){ | |
transform: @thirdSideTransform rotateX(@closeDeg); | |
} | |
&:nth-child(5){ | |
transform: @fourthSideTransform rotateX(@closeDeg); | |
} | |
&::before, | |
&::after{ | |
content: ''; | |
position: absolute; | |
z-index:2; | |
display: block; | |
width: 100%; | |
height: 100%; | |
box-sizing: border-box; | |
box-shadow: inset 0 1px 1rem fadeout(@borderColor, 50%), inset 1px 0 1rem fadeout(@borderColor, 50%), inset 0 -1px 1rem fadeout(@borderColor, 50%), inset -1px 0 1rem fadeout(@borderColor, 50%), 0 1px .3rem fadeout(@borderColor, 50%), 1px 0 .3rem fadeout(@borderColor, 50%), 0 -1px .3rem fadeout(@borderColor, 50%), -1px 0 .3rem fadeout(@borderColor, 50%); | |
} | |
&::before{ | |
transform: skewX(@sideDeg) translateX(-@skewOffset); // todo: calculate | |
border-right: @borderWidth solid @borderColor; | |
} | |
&::after{ | |
transform: skewX(-@sideDeg) translateX(@skewOffset); // todo: calculate | |
border-left: @borderWidth solid @borderColor; | |
} | |
} | |
.animationstate:checked ~ .camera{ | |
.scene{ | |
animation-play-state: running; | |
} | |
} | |
.gutterstate:checked ~ .camera{ | |
.scene::before{ | |
opacity: 1; | |
} | |
} | |
.light{ | |
position: fixed; | |
right: 0; | |
left: 0; | |
height: 60%; | |
transform: rotateX(90deg) translateZ(@b/2); | |
transform-origin: 0 top; | |
animation-play-state: inherit; | |
.incoming{ | |
position: absolute; | |
right: 50%; | |
height: 100%; | |
width: 50%; | |
transform: rotateX(180deg) rotateZ(3deg); | |
animation-play-state: inherit; | |
&::before{ | |
content: ''; | |
position: absolute; | |
top: 0; | |
right: 0; | |
left: -20px; | |
z-index: 2; | |
display: block; | |
width: 100%; | |
height: 100%; | |
box-sizing: border-box; | |
border-right: 12px solid rgba(255,255,255,0.8); | |
transform: skewX(-75deg); | |
transform-origin: 100% 0; | |
animation: pulse 5s infinite, shine .3s linear 1; | |
animation-play-state: inherit; | |
} | |
} | |
.outgoing{ | |
position: absolute; | |
left: 50%; | |
height: 100%; | |
width: 50%; | |
transform-style: preserve-3d; | |
tranform: rotateZ(-3deg); | |
animation-play-state: inherit; | |
} | |
.outgoing{ | |
&::before{ | |
content: ''; | |
position: absolute; | |
top: 0; | |
display: block; | |
width: 100%; | |
height: 50px; | |
background: linear-gradient(to top, #dc1231, #dc1231 16.666% , #e98d14 16.666%, #e98d14 33.332%, #ffff29 33.332%, #ffff29 49.998%, #75bf27 49.998%, #75bf27 66.664%, #73cbee 66.664%, #73cbee 83.333%, #6a518f 83.333%); | |
transform-origin: 0 0; | |
transform: skewX((360deg - @closeDeg - 30deg)*-1) skewY(-17deg) translateY(100px) translateX(100px); | |
animation: discodisco 5s infinite, break .3s linear 1; | |
animation-play-state: inherit; | |
} | |
} | |
} |
First steps, need to sort out perspective stuff with the lights.
A Pen by Mario Nebl on CodePen.