mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 10:11:46 +00:00
263 lines
6.8 KiB
JavaScript
263 lines
6.8 KiB
JavaScript
// Constants
|
|
const element = document.documentElement,
|
|
body = document.body,
|
|
revealOnScroll = (window.sr = ScrollReveal({ mobile: false }));
|
|
|
|
// Load animations
|
|
element.classList.remove("no-js");
|
|
element.classList.add("js");
|
|
window.addEventListener("load", function () {
|
|
body.classList.add("is-loaded");
|
|
});
|
|
|
|
if (body.classList.contains("has-animations")) {
|
|
window.addEventListener("load", function () {
|
|
revealOnScroll.reveal(".feature-extended .device-mockup", {
|
|
duration: 600,
|
|
distance: "100px",
|
|
easing: "cubic-bezier(0.215, 0.61, 0.355, 1)",
|
|
origin: "bottom",
|
|
viewFactor: 0.6,
|
|
});
|
|
revealOnScroll.reveal(".feature-extended .feature-extended-body", {
|
|
duration: 600,
|
|
distance: "40px",
|
|
easing: "cubic-bezier(0.215, 0.61, 0.355, 1)",
|
|
origin: "top",
|
|
viewFactor: 0.6,
|
|
});
|
|
});
|
|
}
|
|
|
|
// Bubble canvas
|
|
let bubbleCanvas = function (t) {
|
|
let e = this;
|
|
e.parentNode = t;
|
|
e.setCanvasSize();
|
|
window.addEventListener("resize", function () {
|
|
e.setCanvasSize();
|
|
});
|
|
e.mouseX = 0;
|
|
e.mouseY = 0;
|
|
window.addEventListener("mousemove", function (t) {
|
|
(e.mouseX = t.clientX), (e.mouseY = t.clientY);
|
|
});
|
|
e.randomise();
|
|
};
|
|
|
|
bubbleCanvas.prototype.setCanvasSize = function () {
|
|
this.canvasWidth = this.parentNode.clientWidth;
|
|
this.canvasHeight = this.parentNode.clientHeight;
|
|
};
|
|
|
|
bubbleCanvas.prototype.generateDecimalBetween = function (start, end) {
|
|
return (Math.random() * (start - end) + end).toFixed(2);
|
|
};
|
|
|
|
bubbleCanvas.prototype.update = function () {
|
|
let t = this;
|
|
t.translateX = t.translateX - t.movementX;
|
|
t.translateY = t.translateY - t.movementY;
|
|
t.posX += (t.mouseX / (t.staticity / t.magnetism) - t.posX) / t.smoothFactor;
|
|
t.posY += (t.mouseY / (t.staticity / t.magnetism) - t.posY) / t.smoothFactor;
|
|
if (
|
|
t.translateY + t.posY < 0 ||
|
|
t.translateX + t.posX < 0 ||
|
|
t.translateX + t.posX > t.canvasWidth
|
|
) {
|
|
t.randomise();
|
|
t.translateY = t.canvasHeight;
|
|
}
|
|
};
|
|
|
|
bubbleCanvas.prototype.randomise = function () {
|
|
this.colors = ["195,53,46", "172,54,46"];
|
|
|
|
this.velocity = 20;
|
|
this.smoothFactor = 50;
|
|
this.staticity = 30;
|
|
this.magnetism = 0.1 + 4 * Math.random();
|
|
this.color = this.colors[Math.floor(Math.random() * this.colors.length)];
|
|
this.alpha = this.generateDecimalBetween(5, 10) / 10;
|
|
this.size = this.generateDecimalBetween(1, 4);
|
|
this.posX = 0;
|
|
this.posY = 0;
|
|
this.movementX = this.generateDecimalBetween(-2, 2) / this.velocity;
|
|
this.movementY = this.generateDecimalBetween(1, 20) / this.velocity;
|
|
this.translateX = this.generateDecimalBetween(0, this.canvasWidth);
|
|
this.translateY = this.generateDecimalBetween(0, this.canvasHeight);
|
|
};
|
|
|
|
let drawBubbleCanvas = function (t) {
|
|
this.canvas = document.getElementById(t);
|
|
this.ctx = this.canvas.getContext("2d");
|
|
this.dpr = window.devicePixelRatio;
|
|
};
|
|
|
|
drawBubbleCanvas.prototype.start = function (bubbleDensity) {
|
|
let t = this;
|
|
t.bubbleDensity = bubbleDensity;
|
|
t.setCanvasSize();
|
|
window.addEventListener("resize", function () {
|
|
t.setCanvasSize();
|
|
});
|
|
t.bubblesList = [];
|
|
t.generateBubbles();
|
|
t.animate();
|
|
};
|
|
|
|
drawBubbleCanvas.prototype.setCanvasSize = function () {
|
|
this.container = this.canvas.parentNode;
|
|
this.w = this.container.offsetWidth;
|
|
this.h = this.container.offsetHeight;
|
|
this.wdpi = this.w * this.dpr;
|
|
this.hdpi = this.h * this.dpr;
|
|
this.canvas.width = this.wdpi;
|
|
this.canvas.height = this.hdpi;
|
|
this.canvas.style.width = this.w + "px";
|
|
this.canvas.style.height = this.h + "px";
|
|
this.ctx.scale(this.dpr, this.dpr);
|
|
};
|
|
|
|
drawBubbleCanvas.prototype.animate = function () {
|
|
let t = this;
|
|
t.ctx.clearRect(0, 0, t.canvas.clientWidth, t.canvas.clientHeight);
|
|
t.bubblesList.forEach(function (e) {
|
|
e.update();
|
|
t.ctx.translate(e.translateX, e.translateY);
|
|
t.ctx.beginPath();
|
|
t.ctx.arc(e.posX, e.posY, e.size, 0, 2 * Math.PI);
|
|
t.ctx.fillStyle = "rgba(" + e.color + "," + e.alpha + ")";
|
|
t.ctx.fill();
|
|
t.ctx.setTransform(t.dpr, 0, 0, t.dpr, 0, 0);
|
|
});
|
|
requestAnimationFrame(this.animate.bind(this));
|
|
};
|
|
|
|
drawBubbleCanvas.prototype.addBubble = function (t) {
|
|
return this.bubblesList.push(t);
|
|
};
|
|
|
|
drawBubbleCanvas.prototype.generateBubbles = function () {
|
|
let t = this;
|
|
for (let e = 0; e < t.bubbleDensity; e++)
|
|
t.addBubble(new bubbleCanvas(t.canvas.parentNode));
|
|
};
|
|
|
|
// Night sky with stars canvas
|
|
let starCanvas = function (t) {
|
|
this.canvas = document.getElementById(t);
|
|
this.ctx = this.canvas.getContext("2d");
|
|
this.dpr = window.devicePixelRatio;
|
|
};
|
|
|
|
starCanvas.prototype.start = function () {
|
|
let w;
|
|
let h;
|
|
|
|
const setCanvasExtents = () => {
|
|
w = this.canvas.parentNode.clientWidth;
|
|
h = this.canvas.parentNode.clientHeight;
|
|
this.canvas.width = w;
|
|
this.canvas.height = h;
|
|
};
|
|
|
|
setCanvasExtents();
|
|
|
|
window.onresize = () => {
|
|
setCanvasExtents();
|
|
};
|
|
|
|
const makeStars = (count) => {
|
|
const out = [];
|
|
for (let i = 0; i < count; i++) {
|
|
const s = {
|
|
x: Math.random() * w - w / 2,
|
|
y: Math.random() * h - h / 2,
|
|
z: Math.random() * 1000,
|
|
};
|
|
out.push(s);
|
|
}
|
|
return out;
|
|
};
|
|
|
|
let stars = makeStars(10000);
|
|
|
|
const clear = () => {
|
|
this.ctx.fillStyle = "#212121";
|
|
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
};
|
|
|
|
const putPixel = (x, y, brightness) => {
|
|
const intensity = brightness * 255;
|
|
const rgb = "rgb(" + intensity + "," + intensity + "," + intensity + ")";
|
|
this.ctx.beginPath();
|
|
this.ctx.arc(x, y, 0.9, 0, 2 * Math.PI);
|
|
this.ctx.fillStyle = rgb;
|
|
this.ctx.fill();
|
|
};
|
|
|
|
const moveStars = (distance) => {
|
|
const count = stars.length;
|
|
for (var i = 0; i < count; i++) {
|
|
const s = stars[i];
|
|
s.z -= distance;
|
|
while (s.z <= 1) {
|
|
s.z += 1000;
|
|
}
|
|
}
|
|
};
|
|
|
|
let prevTime;
|
|
const init = (time) => {
|
|
prevTime = time;
|
|
requestAnimationFrame(tick);
|
|
};
|
|
|
|
const tick = (time) => {
|
|
let elapsed = time - prevTime;
|
|
prevTime = time;
|
|
|
|
moveStars(elapsed * 0.1);
|
|
|
|
clear();
|
|
|
|
const cx = w / 2;
|
|
const cy = h / 2;
|
|
|
|
const count = stars.length;
|
|
for (var i = 0; i < count; i++) {
|
|
const star = stars[i];
|
|
|
|
const x = cx + star.x / (star.z * 0.001);
|
|
const y = cy + star.y / (star.z * 0.001);
|
|
|
|
if (x < 0 || x >= w || y < 0 || y >= h) {
|
|
continue;
|
|
}
|
|
|
|
const d = star.z / 1000.0;
|
|
const b = 1 - d * d;
|
|
|
|
putPixel(x, y, b);
|
|
}
|
|
|
|
requestAnimationFrame(tick);
|
|
};
|
|
|
|
requestAnimationFrame(init);
|
|
};
|
|
|
|
// Start canvas animations
|
|
window.addEventListener("load", function () {
|
|
// Stars
|
|
const headCanvas = new starCanvas("hero-particles");
|
|
// Bubbles
|
|
const footerCanvas = new drawBubbleCanvas("footer-particles");
|
|
const mainCanvas = new drawBubbleCanvas("main-particles");
|
|
|
|
headCanvas.start();
|
|
footerCanvas.start(30);
|
|
mainCanvas.start(200);
|
|
});
|