index/*: Add main title typing animation
This commit is contained in:
parent
ce6309e7a5
commit
f116cc07f2
|
@ -1,2 +1,115 @@
|
||||||
import "bootstrap";
|
import "bootstrap";
|
||||||
import "./index.scss";
|
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);
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
extends ../lib/pug/base
|
extends ../lib/pug/base
|
||||||
|
|
||||||
block content
|
block content
|
||||||
h1.head-line Welcome to tlater.net!
|
noscript
|
||||||
|
style.
|
||||||
|
.head-line .typed {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.head-line
|
||||||
|
| $
|
||||||
|
span.typed Welcome to tlater.net!
|
||||||
h5.tag-line: em Your #1 site for useless time sinks
|
h5.tag-line: em Your #1 site for useless time sinks
|
||||||
|
|
||||||
hr
|
hr
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
@import "../lib/scss/main";
|
@import "../lib/scss/main";
|
||||||
@import "~bootstrap/scss/bootstrap";
|
@import "~bootstrap/scss/bootstrap";
|
||||||
|
|
||||||
|
.head-line .typed {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
Reference in a new issue