Skip to content

Instantly share code, notes, and snippets.

@marionebl
Created September 7, 2014 18:56
Show Gist options
  • Save marionebl/37e9a043970fb40644ef to your computer and use it in GitHub Desktop.
Save marionebl/37e9a043970fb40644ef to your computer and use it in GitHub Desktop.
A Pen by Mario Nebl.
<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;
}
}
}

The Dark Side of the Moon 3D

First steps, need to sort out perspective stuff with the lights.

A Pen by Mario Nebl on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment