// Inverse trigonometric functions with Sass using the infinite series expansion. // Latest version! // First got the idea after seeing this post: // http://www.japborst.net/blog/sass-sines-and-cosines.html // precision could be better with a smaller default error // current default error is 2.5% of a degree // and works well enough // completely useless to make it drop under .5% of a degree $default_err: pi()/14400; @function asin($val, $e: $default_err) { /* * $val: the value for which we compute the arc sine; * $e: tolerated error; lower = better precision * * the function returns the arc sine of $val * * Examples: * asin(.5) returns 29.97584deg (using default tolerated error) * asin(0, pi()/180) returns 0deg */ $sum: 0; // the "infinite" sum we compute $sign: 1; // sign of angle $flag: 0; // 0 if angle in absolute value < 45deg, 1 otherwise $i: 0; // current index $c: 1; $j: 2*$i + 1; @if abs($val) > sin(45deg) { $flag: 1; $sign: $val/abs($val); $val: sqrt(1 - pow($val, 2)); } $term: $c*pow($val, $j)/$j; @while abs($term) > $e { $sum: $sum + $term; $i: $i + 1; $c: $c*(2*$i - 1)/(2*$i); $j: 2*$i + 1; $term: $c*pow($val, $j)/$j; } $result: $sign*($flag*pi()/2 + pow(-1, $flag)*$sum); @return $result/pi()*180deg; } @function acos($val, $e: $default_err) { /* * $val: the value for which we compute the arc cosine * $e: tolerated error; lower = better precision * * the function returns the arc cosine of $val * * Examples: * acos(.5) returns 60.02416deg (using default tolerated error) * acos(0, pi()/180) returns 90deg */ @return 90deg - asin($val, $e); } @function atan($val, $e: $default_err) { /* * $val: the value for which we compute the arc tangent * $e: tolerated error; lower = better precision * * the function returns the arc tangent of $val * * Examples: * atan(1) returns ~45deg (using default tolerated error) * atan(0, pi()/180) returns 0deg */ $val: $val/sqrt(1 + pow($val, 2)); @return asin($val, $e); } $l: 30vmin; $line: 2px; $a: atan(1/sqrt(2)); // atan(ratio between edge & face diagonal in diagonal triangle) $s: 10%; .cube { &, * { position: absolute; top: 50%; left: 50%; } transform-style: preserve-3d; animation: ani 3s cubic-bezier(.86, 0, .07, 1) infinite; /* easings.net/#easeInOutQuint */ } .face { margin: -$l/2; width: $l; height: $l; /* more precise control than dashed border */ background: linear-gradient(currentColor 50%, transparent 50%) repeat-y, linear-gradient(0deg, currentColor 50%, transparent 50%) repeat-y 100% 0, linear-gradient(90deg, currentColor 50%, transparent 50%) repeat-x, linear-gradient(-90deg, currentColor 50%, transparent 50%) repeat-x 0 100%, linear-gradient(45deg, transparent calc(50% - #{$line}), currentColor calc(50% - #{$line}), currentColor calc(50% + #{$line}), transparent calc(50% + #{$line})), linear-gradient(-45deg, transparent calc(50% - #{$line}), currentColor calc(50% - #{$line}), currentColor calc(50% + #{$line}), transparent calc(50% + #{$line})); background-size: $line $s, $line $s, $s $line, $s $line, cover, cover; @for $i from 0 to 6 { &:nth-child(#{$i + 1}) { transform: if($i < 4, rotateY($i*90deg), rotateX(pow(-1, $i)*90deg)) translateZ($l/2) if($i < 4, rotate((1 - pow(-1, $i))*45deg), rotate(90deg)); } } } @keyframes ani { 0%, 5% { transform: rotateX($a) rotateY(-45deg); } 28.333%, 38.333% { transform: rotateX($a) rotateY(45deg); } 61.666%, 71.666% { transform: rotateX($a) rotateY(45deg) rotateX(-90deg); } 95%, 100% { transform: rotateX($a) rotateY(45deg) rotateX(-90deg) rotateY(-90deg); } }