Skip to content

Instantly share code, notes, and snippets.

@artemuzz
Created August 20, 2019 02:49
Show Gist options
  • Save artemuzz/3813ce2f9cdab281f1242deb45987ad1 to your computer and use it in GitHub Desktop.
Save artemuzz/3813ce2f9cdab281f1242deb45987ad1 to your computer and use it in GitHub Desktop.
Blocky Digital Clock
- var blocks = 94;
.container
- var d = 6;
- while (d--) {
.digit
- }
.surface
- for (var b = 1;b <= blocks;++b) {
div(class="block b" + b)
.block-outer
.block-inner
.bottom
.front
.left
.right
- }
window.addEventListener("load",update);
function update() {
let time = new Date(),
hr = time.getHours(),
min = time.getMinutes(),
sec = time.getSeconds();
// prepend 0s to single digits
if (hr < 10)
hr = "0" + hr;
if (min < 10)
min = "0" + min;
if (sec < 10)
sec = "0" + sec;
let timeStr = `${hr}${min}${sec}`,
digits = document.querySelectorAll(".digit"),
digitArr = [];
for (let d in digits) {
d = +d;
if (d < digits.length) {
digitArr[d] = timeStr.substr(d,1);
digits[d].className = "digit _" + digitArr[d];
}
}
setTimeout(update,1000);
}
// container and surface
$sqSize: 20px;
$xSpaces: 27;
$ySpaces: 1;
$zSpaces: 5;
$contW: (1em * $xSpaces) * 1.1;
$contH: 1em * $zSpaces * 2;
$xAngle: 105deg;
$zAngle: 0deg;
$prsp: 800px;
// colors
$tr: transparent;
$bl: #000;
$gry: #444;
$grn: #74d447;
// animation, transitions
$dur: 2s;
$tf: cubic-bezier(.4,.1,.6,.9);
$trans: 0.3s;
$bounce: 10px;
$tilt: 7deg;
// * Block placement *
// parameters: x-pos,z-pos
$blocks:
// * Hour *
// tens
(1,5) (2,5) (3,5)
(1,4) (2,4) (3,4)
(1,3) (2,3) (3,3)
(1,2) (2,2) (3,2)
(1,1) (2,1) (3,1)
// ones
(5,5) (6,5) (7,5)
(5,4) (6,4) (7,4)
(5,3) (6,3) (7,3)
(5,2) (6,2) (7,2)
(5,1) (6,1) (7,1)
// colon
(9,4)
(9,2)
// * Minute *
// tens
(11,5) (12,5) (13,5)
(11,4) (12,4) (13,4)
(11,3) (12,3) (13,3)
(11,2) (12,2) (13,2)
(11,1) (12,1) (13,1)
// ones
(15,5) (16,5) (17,5)
(15,4) (16,4) (17,4)
(15,3) (16,3) (17,3)
(15,2) (16,2) (17,2)
(15,1) (16,1) (17,1)
// colon
(19,4)
(19,2)
// * Second *
// tens
(21,5) (22,5) (23,5)
(21,4) (22,4) (23,4)
(21,3) (22,3) (23,3)
(21,2) (22,2) (23,2)
(21,1) (22,1) (23,1)
// ones
(25,5) (26,5) (27,5)
(25,4) (26,4) (27,4)
(25,3) (26,3) (27,3)
(25,2) (26,2) (27,2)
(25,1) (26,1) (27,1);
@mixin placeBlock($x, $z) {
$w: 0.8; // block width
$d: $w;
$h: $w;
$g: (1 - $w) / 2; // half gap between blocks
$x: $x + $g;
$y: 1 + $g;
$z: $z + $g;
transform: translate3d(
1em*($x - 1),
1em*(-$y - ($d - 1)),
(1em*$z) + (1em*($h - 1))
);
.block-inner div {
&.top, &.bottom {
width: 1em * $w;
height: 1em * $d;
}
&.top {
transform: rotateX(-90deg) translateY(-1em*($d - 1));
}
&.bottom {
transform: rotateX(-90deg) translateY(-1em*($d - 1)) translateZ(1em*$h);
}
&.front, &.back {
width: 1em * $w;
height: 1em * $h;
}
&.front {
transform: translateZ(1em * ($d - 1));
}
&.left, &.right {
width: 1em * $d;
height: 1em * $h;
}
&.right {
transform: rotateY(-270deg) translate3d(1em, 0, 1em*($w - $d));
}
}
}
@mixin moveBlock($x, $z) {
transform: translate3d(1em * $x,0,1em * $z);
}
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background:
radial-gradient(circle at center,$tr, $bl 95%),
linear-gradient($gry 0.1em, $tr 0) 0 0 / 1em 1em,
linear-gradient(90deg, $gry 0.1em, $bl 0) 0 0 / 1em 1em;
font-size: $sqSize;
height: 100vh;
margin: 0;
overflow: hidden;
}
.container, .surface, .block, .block-outer, .block-inner {
transform-style: preserve-3d;
}
.container, .block, .digit {
position: absolute;
}
.container {
animation: bounce $dur $tf infinite;
display: flex;
margin: auto;
overflow: hidden;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: $contW;
height: $contH;
perspective: $prsp;
}
.surface {
animation: tilt $dur (-$dur*0.75) $tf infinite;
display: block;
width: 1em * $xSpaces;
height: 1em * $ySpaces;
margin: auto;
transform: translateY(1em * $zSpaces/2) rotateX($xAngle) rotateZ($zAngle);
will-change: transform;
}
.block {
bottom: 0;
}
.block-inner {
div {
background-color: $grn;
}
> div {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
position: absolute;
width: 1em;
height: 1em;
&.top, &.bottom, &.left, &.right {
&:before {
background-color: #000;
content: "";
width: 100%;
height: 100%;
}
}
&.top, &.bottom {
&:before {
opacity: 0.2;
}
}
&.left, &.right {
&:before {
opacity: 0.4;
}
}
}
}
.block-outer, .block-inner {
position: relative;
width: 1em;
}
.block-outer {
transition: transform $trans;
}
.block-inner {
transform: rotateX(-90deg) translateZ(1em);
}
.back {
transform: translateZ(-1em) rotateY(180deg);
}
.left {
transform-origin: center left;
transform: rotateY(270deg) translateX(-1em);
}
.right {
transform-origin: top right;
}
.top, .bottom {
transform-origin: top center;
}
// * Render blocks *
// one block only
@if length(nth($blocks,1)) == 1 {
.b1 {
@include placeBlock(
nth($blocks, 1),
nth($blocks, 2)
);
}
}
// more than one block
@else {
@for $b from 1 through length($blocks) {
.b#{$b} {
@include placeBlock(
nth(nth($blocks, $b), 1),
nth(nth($blocks, $b), 2)
);
}
}
}
// * Digit display *
@for $p from 1 through 6 {
$step: 15 * ($p - 1);
// deal with colons
$adj: if($p > 4,4,if($p > 2,2,0));
$step: $step + $adj;
._0:nth-of-type(#{$p}) ~ .surface {
.b#{5 + $step}, .b#{8 + $step}, .b#{11 + $step} {
.block-outer {
@include moveBlock(-1,0)
}
}
}
._1:nth-of-type(#{$p}) ~ .surface {
.b#{1 + $step}, .b#{4 + $step}, .b#{7 + $step}, .b#{10 + $step}, .b#{13 + $step} {
.block-outer {
@include moveBlock(2,0)
}
}
.b#{2 + $step}, .b#{5 + $step}, .b#{8 + $step}, .b#{11 + $step}, .b#{14 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
}
._2:nth-of-type(#{$p}) ~ .surface {
.b#{4 + $step} {
.block-outer {
@include moveBlock(2,0)
}
}
.b#{5 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
.b#{11 + $step} {
.block-outer {
@include moveBlock(-1,0)
}
}
.b#{12 + $step} {
.block-outer {
@include moveBlock(-2,0)
}
}
}
@if $p > 1 {
._3:nth-of-type(#{$p}) ~ .surface {
.b#{4 + $step}, .b#{10 + $step} {
.block-outer {
@include moveBlock(2,0)
}
}
.b#{5 + $step}, .b#{11 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
}
._4:nth-of-type(#{$p}) ~ .surface {
.b#{2 + $step}, .b#{5 + $step} {
.block-outer {
@include moveBlock(-1,0)
}
}
.b#{10 + $step}, .b#{13 + $step} {
.block-outer {
@include moveBlock(2,0)
}
}
.b#{11 + $step}, .b#{14 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
}
._5:nth-of-type(#{$p}) ~ .surface {
.b#{5 + $step} {
.block-outer {
@include moveBlock(-1,0)
}
}
.b#{6 + $step} {
.block-outer {
@include moveBlock(-2,0)
}
}
.b#{10 + $step} {
.block-outer {
@include moveBlock(2,0)
}
}
.b#{11 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
}
@if $p % 2 == 0 {
._6:nth-of-type(#{$p}) ~ .surface {
.b#{5 + $step} {
.block-outer {
@include moveBlock(-1,0)
}
}
.b#{6 + $step} {
.block-outer {
@include moveBlock(-2,0)
}
}
.b#{11 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
}
._7:nth-of-type(#{$p}) ~ .surface {
.b#{4 + $step}, .b#{7 + $step}, .b#{10 + $step}, .b#{13 + $step} {
.block-outer {
@include moveBlock(2,0)
}
}
.b#{5 + $step}, .b#{8 + $step}, .b#{11 + $step}, .b#{14 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
}
._8:nth-of-type(#{$p}) ~ .surface {
.b#{5 + $step}, .b#{11 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
}
._9:nth-of-type(#{$p}) ~ .surface {
.b#{5 + $step}, .b#{11 + $step} {
.block-outer {
@include moveBlock(1,0)
}
}
.b#{10 + $step} {
.block-outer {
@include moveBlock(2,0)
}
}
}
}
}
}
/* Animations */
@keyframes bounce {
from, 50%, to {
transform: translateY(0);
}
25%, 75% {
transform: translateY($bounce);
}
}
@keyframes tilt {
from, to {
transform: translateY(1em * $zSpaces/2) rotateX($xAngle) rotateZ(-$tilt);
}
50% {
transform: translateY(1em * $zSpaces/2) rotateX($xAngle) rotateZ($tilt);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment