<html>
<head>
<meta charset="utf-8">
<title>SCSS Loops for dot matrix</title>
</script>
</head>
<body>
<section class="matrix gradient">
<div class="matrix__inner">
</div>
</section>
</body>
</html>
/*
Rules:
No decimal values, only whole numbers.
We can utilize Expressions to generate variations in values, eg. (x^2 - 2x) where x equals our $row or $column
These expressions can be easily worked with on Wolframalpha
TODO: What is our 0-point, is it the 50% mark or is it the first value in matrix?
*/
html {
box-sizing: border-box;
}
body {
background: #af8686;
// perspective: 500px;
}
:root {
--PI: 3.14159265358979;
}
// Trigonometry
// src: https://gist.github.com/stereokai/7666bfe93929b14c2dced148c79e0e97
// Sine function representation
.sin {
--sin-term1: var(--angle);
--sin-term2: calc((var(--angle) * var(--angle) * var(--angle)) / 6);
--sin-term3: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 120);
--sin-term4: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 5040);
--sin-term5: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 362880);
--sin: calc(var(--sin-term1) - var(--sin-term2) + var(--sin-term3) - var(--sin-term4) + var(--sin-term5));
}
// Cosine function representation
.cos {
--cos-term1: 1;
--cos-term2: calc((var(--angle) * var(--angle)) / 2);
--cos-term3: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 24);
--cos-term4: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 720);
--cos-term5: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 40320);
--cos: calc(var(--cos-term1) - var(--cos-term2) + var(--cos-term3) - var(--cos-term4) + var(--cos-term5));
}
// Tangent function representation
.tan {
--tan-term1: var(--angle);
--tan-term2: calc((1/3) * var(--angle) * var(--angle) * var(--angle));
--tan-term3: calc((2 / 15) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle));
--tan-term4: calc((17/315) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle));
--tan: calc(var(--tan-term1) + var(--tan-term2) + var(--tan-term3) + var(--tan-term4));
}
// Handy functions
@function pow($number, $exponent) {
@if (round($exponent) != $exponent) {
@return exp($exponent * ln($number));
}
$value: 1;
@if $exponent > 0 {
@for $i from 1 through $exponent {
$value: $value * $number;
}
} @else if $exponent < 0 {
@for $i from 1 through -$exponent {
$value: $value / $number;
}
}
@return $value;
}
@function factorial($value) {
$result: 1;
@if $value == 0 {
@return $result;
}
@for $index from 1 through $value {
$result: $result * $index;
}
@return $result;
}
@function summation($iteratee, $input, $initial: 0, $limit: 100) {
$sum: 0;
@for $index from $initial to $limit {
$sum: $sum + call($iteratee, $input, $index);
}
@return $sum;
}
@function exp-maclaurin($x, $n) {
@return (pow($x, $n) / factorial($n));
}
@function exp($value) {
@return summation('exp-maclaurin', $value, 0, 100);
}
@function ln-maclaurin($x, $n) {
@return (pow(-1, $n + 1) / $n) * (pow($x - 1, $n));
}
@function ln($value) {
$ten-exp: 1;
$ln-ten: 2.30258509;
@while ($value > pow(10, $ten-exp)) {
$ten-exp: $ten-exp + 1;
}
@return summation(ln-maclaurin, $value / pow(10, $ten-exp), 1, 100) + $ten-exp * $ln-ten;
}
// Initial styles
*, *:before, *:after {
box-sizing: inherit;
}
.matrix {
height: 100vh;
max-width: 600px;
max-height: 600px;
margin: 0 auto;
margin-top: 5%;
/*
width: 300px; height: 300px;
-webkit-perspective: 1600px;
-webkit-perspective-origin: 50% -240px;
*/
&__inner {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-flow: wrap;
transform: perspective(1000px) rotateX(56deg) rotateZ(-16deg);
transform: rotateX(-60deg) rotateZ(-40deg) translateX(50px) translateY(300px);
transform:rotateX(45deg);
transform: rotateX(-45deg) rotateY(0deg) rotateZ(45deg);
transform-style: preserve-3d;
}
.dot {
position: relative;
width: 10%;
height: 10%;
transition: background-color 3s;
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
transform-style: preserve-3d;
backface-visibility: hidden;
&__inner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #fafafa;
border: 1px solid rgba(0,0,0,1);
}
}
/************* Different modes TODO *************/
// Gradient
//
// Just one line to be right, repeat for every line, could have an angle to work with.
&.gradient {
@for $r from 0 through 9 {
$rowStart: ($r * 10 + 1);
@for $c from 0 through 9 {
div.dot:nth-child(#{$rowStart + $c}) {
.dot__inner {
background-color: lighten(#000, ($c * (100/9)));
animation-delay: $c * 0.1s + $r * 0.025s;
animation-name: gradientWobble;
animation-duration: 6s;
animation-iteration-count: infinite;
}
}
}
}
/* ---------------------- NOT USED ---------------------- */
/* Working with matrix*/
$lowestZ: 0px;
$highestZ: 0px;
// Highest and lowest values
@for $r from 0 through 9 {
$rowStart: ($r * 10 + 1);
$row: $r;
@for $c from 0 through 9 {
$columnStart: $rowStart + $c;
$column: $c;
// Work with row values
$valueX: pow($rowStart, 2) + 5;
@if $row == 0 {
$valueX: 0;
}
// Work with column values
$valueY: pow($columnStart, 2) + 5;
$valueY: 0;
@if $column == 0 {
$valueY: 0;
}
// Working on translate Z
div.dot:nth-child(#{$columnStart}) {
.dot__inner {
@if $lowestZ > $valueX * 0.01px {
$lowestZ: $valueX * 0.01px;
}
@if $highestZ < $valueX * 0.01px {
$highestZ: $valueX * 0.01px;
}
}
}
}
}
/* ---------------------- NOT USED END ---------------------- */
// Expression: x^2 + 4
@for $r from 0 through 9 {
$rowStart: ($r * 10 + 1);
$row: $r;
@for $c from 0 through 9 {
$columnStart: $rowStart + $c;
$column: $c;
// Work with row values
$valueX: pow($rowStart, 2) + 4;
@if $row == 0 {
$valueX: 0;
}
// Work with column values
$valueY: pow($columnStart, 2) + 4;
$valueY: 0;
@if $column == 0 {
$valueY: 0;
}
// Working on translate Z
div.dot:nth-child(#{$columnStart}) {
.dot__inner {
$hslColor: (($c + $r) * 15deg) % 360;
animation-delay: $c * 0.1s + $r * 0.2s;
animation-name: gradientWobble_ + $r + $c;
// transform: translateZ($valueY * 1px + $valueX * 0.01px);
// transform: translateZ($valueX * 0.01px);
// Set so that depending on the column, are we applying generated Z.value or min Z-value.
// $zCalculated: (($lowestZ * $c) * (10 / ($c + 1))) + (($valueX * 0.1px) * (10 / $columnStart));
//$calcZ: ($valueX * 0.01px) * (10 / $c);
//$smallerZ: ($lowestZ * $c) * (10 / ($c + 1));
//$zCalculated: $calcZ + $smallerZ;
// transform: translateZ($zCalculated);
// Hue
background-color: hsl($hslColor, 50%, 50%);
@keyframes #{gradientWobble_ + $r + $c} {
0% {transform: translateZ(0px);}
50% {transform: translateZ(($valueX + $valueY) * 0.025px);}
100% {transform: translateZ(0px);}
}
}
}
}
}
/*
@keyframes gradientWobble {
0% {transform: translateZ(0px);}
50% {transform: translateZ(-25px);}
100% {transform: translateZ(0px);}
}
*/
}
}
View Compiled
let matrix = document.querySelector('.matrix__inner');
document.addEventListener("DOMContentLoaded", function() {
for (let i = 0; i < 100; i++) {
matrix.innerHTML += '<div class="dot item-' + i + '"><div class="dot__inner"></div></div>';
}
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.