mirror of
https://github.com/acid-info/new-codex.storage.git
synced 2026-08-30 21:01:08 +00:00
485 lines
11 KiB
JavaScript
485 lines
11 KiB
JavaScript
import { waitForVariable } from "./helpers.js";
|
|
|
|
{
|
|
const link = document.createElement("link");
|
|
link.rel = "stylesheet";
|
|
link.href = "https://unpkg.com/splitting/dist/splitting.css";
|
|
document.head.appendChild(link);
|
|
}
|
|
|
|
{
|
|
const link = document.createElement("link");
|
|
link.rel = "stylesheet";
|
|
link.href = "https://unpkg.com/splitting/dist/splitting-cells.css";
|
|
document.head.appendChild(link);
|
|
}
|
|
|
|
await waitForVariable("Splitting");
|
|
await waitForVariable("_");
|
|
|
|
(function (w, d) {
|
|
const options = ["ⓒ", "🅾", "Ɗ", "ė", "✖"],
|
|
hovers = ["hover", "hover2"],
|
|
map = {};
|
|
|
|
const setup = () => {
|
|
w.onresize = _.debounce(() => redraw(), 250);
|
|
|
|
d.onmousemove = (mev) => {
|
|
addAnim(mev.target, mev.buttons);
|
|
};
|
|
const getEl = (x, y) => {
|
|
if (map[x + "_" + y]) return map[x + "_" + y];
|
|
let e = d.elementFromPoint(x, y);
|
|
if (e) map[x + "_" + y] = e;
|
|
return e;
|
|
};
|
|
const touchHandler = (tev) => {
|
|
tev.preventDefault();
|
|
for (let i = 0; i < tev.changedTouches.length; i++) {
|
|
let el = getEl(
|
|
tev.changedTouches[i].pageX,
|
|
tev.changedTouches[i].pageY
|
|
);
|
|
if (el) addAnim(el);
|
|
}
|
|
};
|
|
d.addEventListener("touchstart", _.debounce(touchHandler, 250), false);
|
|
d.addEventListener("touchmove", touchHandler, false);
|
|
redraw();
|
|
};
|
|
|
|
const addAnim = (target, buttonPressed) => {
|
|
if (target.nodeName != "SPAN") return;
|
|
target.className = _.sample(hovers);
|
|
if (buttonPressed)
|
|
target.style.color = "#000000".replace(/0/g, function () {
|
|
return (~~(Math.random() * 16)).toString(16);
|
|
});
|
|
target.innerHTML = _.sample(options);
|
|
_.delay(() => {
|
|
if (target.className.indexOf("hover") != -1) {
|
|
target.className = "";
|
|
}
|
|
}, 750);
|
|
};
|
|
|
|
const redraw = () => {
|
|
let wh = d.clientHeight,
|
|
ww = window.outerWidth,
|
|
/*These arrays are to workaround CodePen's infinite loop "feature", large for-loops seem to trigger the error even if the loop isn't actually infinite :/ - Creating arrays padded with zeroes and using forEach seems to work (for now!!).*/
|
|
cols = new Array((ww / 15) | 0).join("0").split(""),
|
|
rows = new Array((wh / 15) | 0).join("0").split(""),
|
|
rh = [],
|
|
top = 5;
|
|
d.innerHTML = "";
|
|
rows.forEach(() => {
|
|
let spans = 0;
|
|
cols.forEach(() => spans++);
|
|
rh.push(spans);
|
|
});
|
|
rh.forEach((r) => {
|
|
if (r == rh[0]) {
|
|
let row = '<div class="row">',
|
|
left = 10;
|
|
new Array(r)
|
|
.join("0")
|
|
.split("")
|
|
.forEach(() => {
|
|
row += `<span style="left:${left}px; top: ${top}px">+</span>`;
|
|
left += 15;
|
|
});
|
|
row += "</div>";
|
|
d.innerHTML += row;
|
|
top += 15;
|
|
}
|
|
});
|
|
};
|
|
|
|
setup();
|
|
})(window, document.getElementById("background"));
|
|
|
|
{
|
|
let footer = document.querySelector(".team footer");
|
|
if (footer) {
|
|
console.info("Registering team footer event");
|
|
let isDown = false;
|
|
let startX;
|
|
let scrollLeft;
|
|
|
|
footer.addEventListener("mousedown", (e) => {
|
|
isDown = true;
|
|
startX = e.pageX - footer.offsetLeft;
|
|
scrollLeft = footer.scrollLeft;
|
|
});
|
|
footer.addEventListener("mouseleave", () => {
|
|
isDown = false;
|
|
});
|
|
footer.addEventListener("mouseup", () => {
|
|
isDown = false;
|
|
});
|
|
footer.addEventListener("mousemove", (e) => {
|
|
if (!isDown) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
const x = e.pageX - footer.offsetLeft;
|
|
const walk = x - startX; //scroll-fast
|
|
footer.scrollLeft = scrollLeft - walk;
|
|
});
|
|
}
|
|
}
|
|
|
|
// ///////////////////////////////////////////
|
|
const randomNumber = (min, max) =>
|
|
Math.floor(Math.random() * (max - min + 1)) + min;
|
|
|
|
/**
|
|
* Class representing one line
|
|
*/
|
|
class Line {
|
|
// line position
|
|
position = -1;
|
|
// cells/chars
|
|
cells = [];
|
|
|
|
/**
|
|
* Constructor.
|
|
* @param {Element} DOM_el - the char element (<span>)
|
|
*/
|
|
constructor(linePosition) {
|
|
this.position = linePosition;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Class representing one cell/char
|
|
*/
|
|
class Cell {
|
|
// DOM elements
|
|
DOM = {
|
|
// the char element (<span>)
|
|
el: null,
|
|
};
|
|
// cell position
|
|
position = -1;
|
|
// previous cell position
|
|
previousCellPosition = -1;
|
|
// original innerHTML
|
|
original;
|
|
// current state/innerHTML
|
|
state;
|
|
color;
|
|
originalColor;
|
|
// cached values
|
|
cache;
|
|
|
|
/**
|
|
* Constructor.
|
|
* @param {Element} DOM_el - the char element (<span>)
|
|
*/
|
|
constructor(DOM_el, { position, previousCellPosition } = {}) {
|
|
this.DOM.el = DOM_el;
|
|
this.original = this.DOM.el.innerHTML;
|
|
this.state = this.original;
|
|
this.color = this.originalColor = getComputedStyle(
|
|
document.documentElement
|
|
).getPropertyValue("--color-text");
|
|
this.position = position;
|
|
this.previousCellPosition = previousCellPosition;
|
|
}
|
|
/**
|
|
* @param {string} value
|
|
*/
|
|
set(value) {
|
|
this.state = value;
|
|
this.DOM.el.innerHTML = this.state;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Class representing the TypeShuffle object
|
|
*/
|
|
export class TypeShuffle {
|
|
// DOM elements
|
|
DOM = {
|
|
// the main text element
|
|
el: null,
|
|
};
|
|
// array of Line objs
|
|
lines = [];
|
|
// array of letters and symbols
|
|
lettersAndSymbols = [
|
|
"A",
|
|
"B",
|
|
"C",
|
|
"D",
|
|
"E",
|
|
"F",
|
|
"G",
|
|
"H",
|
|
"I",
|
|
"J",
|
|
"K",
|
|
"L",
|
|
"M",
|
|
"N",
|
|
"O",
|
|
"P",
|
|
"Q",
|
|
"R",
|
|
"S",
|
|
"T",
|
|
"U",
|
|
"V",
|
|
"W",
|
|
"X",
|
|
"Y",
|
|
"Z",
|
|
"!",
|
|
"@",
|
|
"#",
|
|
"$",
|
|
"&",
|
|
"*",
|
|
"(",
|
|
")",
|
|
"-",
|
|
"_",
|
|
"+",
|
|
"=",
|
|
"/",
|
|
"[",
|
|
"]",
|
|
"{",
|
|
"}",
|
|
";",
|
|
":",
|
|
"<",
|
|
">",
|
|
",",
|
|
"0",
|
|
"1",
|
|
"2",
|
|
"3",
|
|
"4",
|
|
"5",
|
|
"6",
|
|
"7",
|
|
"8",
|
|
"9",
|
|
];
|
|
// effects and respective methods
|
|
effects = {
|
|
fx1: () => this.fx1(),
|
|
fx2: () => this.fx2(),
|
|
fx3: () => this.fx3(),
|
|
fx4: () => this.fx4(),
|
|
fx5: () => this.fx5(),
|
|
fx6: () => this.fx6(),
|
|
};
|
|
totalChars = 0;
|
|
|
|
/**
|
|
* Constructor.
|
|
* @param {Element} DOM_el - main text element
|
|
*/
|
|
constructor(DOM_el) {
|
|
this.DOM.el = DOM_el;
|
|
// Apply Splitting (two times to have lines, words and chars)
|
|
const results = Splitting({
|
|
target: this.DOM.el,
|
|
by: "lines",
|
|
});
|
|
results.forEach((s) => Splitting({ target: s.words }));
|
|
|
|
// for every line
|
|
for (const [linePosition, lineArr] of results[0].lines.entries()) {
|
|
// create a new Line
|
|
const line = new Line(linePosition);
|
|
let cells = [];
|
|
let charCount = 0;
|
|
// for every word of each line
|
|
for (const word of lineArr) {
|
|
// for every character of each line
|
|
for (const char of [...word.querySelectorAll(".char")]) {
|
|
cells.push(
|
|
new Cell(char, {
|
|
position: charCount,
|
|
previousCellPosition: charCount === 0 ? -1 : charCount - 1,
|
|
})
|
|
);
|
|
++charCount;
|
|
}
|
|
}
|
|
line.cells = cells;
|
|
this.lines.push(line);
|
|
this.totalChars += charCount;
|
|
}
|
|
|
|
// TODO
|
|
// window.addEventListener('resize', () => this.resize());
|
|
}
|
|
/**
|
|
* clear all the cells chars
|
|
*/
|
|
clearCells() {
|
|
for (const line of this.lines) {
|
|
for (const cell of line.cells) {
|
|
cell.set(" ");
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
*
|
|
* @returns {string} a random char from this.lettersAndSymbols
|
|
*/
|
|
getRandomChar() {
|
|
return this.lettersAndSymbols[
|
|
Math.floor(Math.random() * this.lettersAndSymbols.length)
|
|
];
|
|
}
|
|
fx6() {
|
|
// max iterations for each cell to change the current value
|
|
const MAX_CELL_ITERATIONS = 10;
|
|
let finished = 0;
|
|
const loop = (line, cell, iteration = 0) => {
|
|
cell.cache = { state: cell.state, color: cell.color };
|
|
|
|
if (iteration === MAX_CELL_ITERATIONS - 1) {
|
|
cell.set(cell.original);
|
|
|
|
cell.color = cell.originalColor;
|
|
cell.DOM.el.style.color = cell.color;
|
|
|
|
++finished;
|
|
if (finished === this.totalChars) {
|
|
this.isAnimating = false;
|
|
}
|
|
} else {
|
|
cell.set(this.getRandomChar());
|
|
|
|
cell.color = ["#2b4539", "#61dca3", "#61b3dc"][
|
|
Math.floor(Math.random() * 3)
|
|
];
|
|
cell.DOM.el.style.color = cell.color;
|
|
}
|
|
|
|
++iteration;
|
|
if (iteration < MAX_CELL_ITERATIONS) {
|
|
setTimeout(() => loop(line, cell, iteration), randomNumber(30, 110));
|
|
}
|
|
};
|
|
|
|
for (const line of this.lines) {
|
|
for (const cell of line.cells) {
|
|
setTimeout(() => loop(line, cell), (line.position + 1) * 80);
|
|
}
|
|
}
|
|
|
|
// setTimeout(function () {
|
|
// ts.reset();
|
|
// }, 1500);
|
|
}
|
|
|
|
reset() {
|
|
for (const line of this.lines) {
|
|
for (const cell of line.cells) {
|
|
cell.set(cell.original);
|
|
cell.color = cell.originalColor;
|
|
cell.DOM.el.style.color = cell.originalColor;
|
|
}
|
|
}
|
|
this.isAnimating = false;
|
|
}
|
|
/**
|
|
* call the right effect method (defined in this.effects)
|
|
* @param {string} effect - effect type
|
|
*/
|
|
trigger(effect = "fx1") {
|
|
if (!(effect in this.effects) || this.isAnimating) return;
|
|
this.isAnimating = true;
|
|
this.effects[effect]();
|
|
}
|
|
}
|
|
|
|
let ts;
|
|
|
|
const observer = new IntersectionObserver(
|
|
(entries, obs) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
// Only run once per element
|
|
// obs.unobserve(entry.target);
|
|
// Run the effect
|
|
ts = new TypeShuffle(entry.target);
|
|
ts.trigger("fx6");
|
|
}
|
|
});
|
|
},
|
|
{
|
|
threshold: 0.5, // Adjust as needed (0.5 = 50% visible)
|
|
}
|
|
);
|
|
|
|
document
|
|
.querySelectorAll("section header p")
|
|
.forEach((p) => observer.observe(p));
|
|
|
|
document
|
|
.querySelectorAll("section header span")
|
|
.forEach((p) => observer.observe(p));
|
|
|
|
document.querySelector(".discover").onmouseenter = (e) => {
|
|
ts = new TypeShuffle(e.target);
|
|
ts.trigger("fx6");
|
|
};
|
|
|
|
document.querySelectorAll("#menu nav a").forEach((item) => {
|
|
ts = new TypeShuffle(item);
|
|
ts.trigger("fx6");
|
|
});
|
|
|
|
/////////////////////////////////////////
|
|
const header = document.querySelector("body > header");
|
|
let lastScroll = 0;
|
|
|
|
const validateHeader = () => {
|
|
const windowY = window.scrollY;
|
|
const windowH = window.innerHeight;
|
|
|
|
if (windowY > windowH) {
|
|
// We passed the first section, set a toggable class
|
|
header.classList.add("is-fixed");
|
|
} else {
|
|
header.classList.remove("is-fixed", "can-animate");
|
|
}
|
|
|
|
if (windowY > windowH + 40) {
|
|
header.classList.add("can-animate");
|
|
} else {
|
|
header.classList.remove("scroll-up");
|
|
}
|
|
|
|
if (windowY < lastScroll) {
|
|
header.classList.add("scroll-up");
|
|
} else {
|
|
header.classList.remove("scroll-up");
|
|
}
|
|
|
|
lastScroll = windowY;
|
|
};
|
|
|
|
const throttle = (func, time = 100) => {
|
|
let lastTime = 0;
|
|
return () => {
|
|
const now = new Date();
|
|
if (now - lastTime >= time) {
|
|
func();
|
|
time = now;
|
|
}
|
|
};
|
|
};
|
|
|
|
window.addEventListener("scroll", throttle(validateHeader, 100));
|