135 lines
3.8 KiB
SCSS
135 lines
3.8 KiB
SCSS
@use "sass:math";
|
|
@use "sass:list";
|
|
|
|
/// Animate a blinking cursor.
|
|
@mixin cursor($duration) {
|
|
$name: cursor-09d03260130069771b6ddc1cb415f39fdd27ddfab7b01ba91273398c2d245ae4;
|
|
// The number of times we need to blink is = the number of full
|
|
// seconds (500ms * 2) that fit in the total duration, rounded up,
|
|
// and doubled.
|
|
$iterations: math.ceil(math.div($duration, 1s)) * 2;
|
|
|
|
animation: $name ease-in-out 500ms $iterations alternate;
|
|
content: " ";
|
|
|
|
@keyframes #{$name} {
|
|
from {
|
|
content: " ";
|
|
}
|
|
|
|
to {
|
|
content: "█";
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Animate a piece of text as if it was being typed by a human.
|
|
@mixin typed($text, $duration) {
|
|
// We don't want a linearly typed set of text, which makes this
|
|
// singificantly more complex.
|
|
//
|
|
// CSS animations normally do not permit per-frame changes in
|
|
// duration (since the total animation time is fixed). This means we
|
|
// need to create multiple animations, and delay them so that they
|
|
// happen in the time sequence we want.
|
|
//
|
|
// We generate the raw values with _generate-animations, and then
|
|
// split up the result into the animation API.
|
|
$frames: str-length($text);
|
|
$animations: _generate-animations($frames, 1.2s);
|
|
|
|
animation-name: _unzip($animations, 1);
|
|
animation-delay: _unzip($animations, 3);
|
|
animation-fill-mode: forwards;
|
|
content: "";
|
|
|
|
// We need to type each character in separate animations, see above
|
|
// comment.
|
|
@each $name, $character in $animations {
|
|
@keyframes #{$name} {
|
|
from {
|
|
content: str-slice($text, 0, $character);
|
|
}
|
|
|
|
to {
|
|
content: str-slice($text, 0, $character + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Unzip a nested set of lists, taking the nth value of each sublist.
|
|
@function _unzip($lists, $i) {
|
|
$out: ();
|
|
$sep: comma;
|
|
@each $sublist in $lists {
|
|
$out: list.append($out, list.nth($sublist, $i), $sep);
|
|
}
|
|
@return $out;
|
|
}
|
|
|
|
/// Compute the sum of all numbers in a list.
|
|
@function _sum($list) {
|
|
$out: 0;
|
|
@each $val in $list {
|
|
$out: $out + $val;
|
|
}
|
|
@return $out;
|
|
}
|
|
|
|
/// Produce a list from a shorter list by repeating it up until size
|
|
/// $length.
|
|
@function _round-robin($base, $length) {
|
|
$out: ();
|
|
$sep: list.separator($out);
|
|
@for $i from 0 through $length {
|
|
$out: list.append($out, list.nth($base, $i % list.length($base) + 1));
|
|
}
|
|
@return $out;
|
|
}
|
|
|
|
/// Generate the actual animation values.
|
|
///
|
|
/// This generates a nested list as:
|
|
///
|
|
/// (keyframe-name, index, start time)
|
|
///
|
|
/// The duration of each frame is taken from the internal $delays in a
|
|
/// round robin fashion, to give some amount of human-like variance to
|
|
/// the duration of each frame.
|
|
///
|
|
/// Start time is set to the time at which the frame should start to
|
|
/// achieve the desired frame-by-frame duration.
|
|
@function _generate-animations($number, $total_duration) {
|
|
$id: d66fa0449c0b4d4ca287f8c96428af928b2987b4d88b72b7d60152d9a55d9f29;
|
|
$out: ();
|
|
$sep: list.separator($out);
|
|
|
|
// A set of "human-like" delays for each typed character. In
|
|
// practice, my typing seems to be about 20-70ms, but it looks a bit
|
|
// nicer to increase all typing by 20ms to make the effect more
|
|
// noticeable.
|
|
//
|
|
// Numbers generated once with a random number generator, rather
|
|
// than using `math.random()`, since they end up in CSS verbatim,
|
|
// and the build would be non-reproducible if we didn't do it this
|
|
// way. Using `math.random() wouldn't change this dynamically each
|
|
// time the page loads anyway, so we don't really lose anything by
|
|
// pre-generating these numbers.
|
|
$delays: 69ms, 83ms, 49ms, 48ms, 52ms, 59ms, 40ms, 71ms, 80ms, 67ms;
|
|
|
|
@for $animation from 0 through $number {
|
|
$out: list.append(
|
|
$out,
|
|
(
|
|
type-#{$id}-#{$animation},
|
|
$animation,
|
|
_sum(_round_robin($delays, $animation))
|
|
),
|
|
$sep
|
|
);
|
|
}
|
|
|
|
@return $out;
|
|
}
|