index/*: Add main title typing animation

This commit is contained in:
Tristan Maat 2018-04-08 20:49:17 +00:00
parent ce6309e7a5
commit f116cc07f2
3 changed files with 126 additions and 1 deletions

View file

@ -1,2 +1,115 @@
import "bootstrap";
import "./index.scss";
// Helpers
/**
* "Types" out a DOM element, emulating the way a human might.
*/
class Typer {
/**
* Create the typer.
* @param {HTMLElement} element - The element to type.
* @param {number} blink - The time between cursor blinks.
* @param {number} blink_timeout - How long the cursor should keep
* blinking for after the text
* finishes typing.
*/
constructor(element, blink, blink_timeout) {
// Retrieve the current content and wipe it. We also make the
// element visible if it was hidden.
this._element = $(element);
this._text = this._element.html();
this._element.html("");
this._element.css("visibility", "visible");
this._cursor = false;
this._typed = 0;
this._min = 20;
this._max = 70;
this._blink_tick = blink;
this._blink_timeout = blink_timeout;
this._end = null;
}
/**
* Start typing.
*/
type() {
this._type();
this._blink();
}
/**
* Draw the current text line, i.e., anything that has been typed
* so far, and a cursor if it is currently supposed to be on.
* @private
*/
_draw() {
let text = this._text.slice(0, this._typed);
if (this._cursor)
text += "\u2588";
window.requestAnimationFrame(() => this._element.html(text));
}
/**
* Type the next character, and prepare to draw the next one. If
* no new characters are to be drawn, set the end timestamp.
* @private
*/
_type() {
this._typed += 1;
this._draw();
if (this._typed != this._text.length)
setTimeout(this._type.bind(this), this._type_tick());
else
this._end = Date.now();
}
/**
* Make the cursor change blink status, and prepare for the next
* blink.
* @private
*/
_blink() {
this._cursor = !this._cursor;
this._draw();
// As long as we are typing, keep blinking
if (this._typed != this._text.length)
setTimeout(this._blink.bind(this), this._blink_tick);
// Once typing ends, keep going for a little bit
else if (Date.now() - this._end < this._blink_timeout)
setTimeout(this._blink.bind(this), this._blink_tick);
// Make sure we get rid of the cursor in the end
else {
this._cursor = true;
setTimeout(this._blink.bind(this), this._blink_tick);
}
}
/**
* Calculate a "human" time for the next character to type.
* @private
*/
_type_tick() {
return Math.round(Math.random() * this._max) + this._min;
}
}
// Application code
function main() {
// Type the head line
let typer = new Typer($(".head-line .typed").get(0), 500, 3000);
typer.type();
}
$(document).ready(main);

View file

@ -1,7 +1,15 @@
extends ../lib/pug/base
block content
h1.head-line Welcome to tlater.net!
noscript
style.
.head-line .typed {
visibility: visible;
}
h1.head-line
| $&nbsp;
span.typed Welcome to tlater.net!
h5.tag-line: em Your #1 site for useless time sinks
hr

View file

@ -1,2 +1,6 @@
@import "../lib/scss/main";
@import "~bootstrap/scss/bootstrap";
.head-line .typed {
visibility: hidden;
}