<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>';
    }
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.