Created
September 10, 2024 06:01
-
-
Save vladimirlukyanov/dffd86b9fcad850de0937df7481d1005 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { PI, cos, sin, abs, sqrt, pow, round, random, atan2 } = Math; | |
const HALF_PI = 0.5 * PI; | |
const TAU = 2 * PI; | |
const TO_RAD = PI / 180; | |
const floor = n => n | 0; | |
const rand = n => n * random(); | |
const randIn = (min, max) => rand(max - min) + min; | |
const randRange = n => n - rand(2 * n); | |
const fadeIn = (t, m) => t / m; | |
const fadeOut = (t, m) => (m - t) / m; | |
const fadeInOut = (t, m) => { | |
let hm = 0.5 * m; | |
return abs((t + hm) % m - hm) / (hm); | |
}; | |
const dist = (x1, y1, x2, y2) => sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)); | |
const angle = (x1, y1, x2, y2) => atan2(y2 - y1, x2 - x1); | |
const lerp = (n1, n2, speed) => (1 - speed) * n1 + speed * n2; | |
!function() { | |
"use strict"; | |
var r = .5 * (Math.sqrt(3) - 1), | |
e = (3 - Math.sqrt(3)) / 6, | |
t = 1 / 6, | |
a = (Math.sqrt(5) - 1) / 4, | |
o = (5 - Math.sqrt(5)) / 20; | |
function i(r) { | |
var e; | |
e = "function" == typeof r ? r : r ? function() { | |
var r = 0, | |
e = 0, | |
t = 0, | |
a = 1, | |
o = (i = 4022871197, function(r) { | |
r = r.toString(); | |
for (var e = 0; e < r.length; e++) { | |
var t = .02519603282416938 * (i += r.charCodeAt(e)); | |
t -= i = t >>> 0, | |
i = (t *= i) >>> 0, | |
i += 4294967296 * (t -= i) | |
} | |
return 2.3283064365386963e-10 * (i >>> 0) | |
}); | |
var i; | |
r = o(" "), | |
e = o(" "), | |
t = o(" "); | |
for (var n = 0; n < arguments.length; n++) | |
(r -= o(arguments[n])) < 0 && (r += 1), | |
(e -= o(arguments[n])) < 0 && (e += 1), | |
(t -= o(arguments[n])) < 0 && (t += 1); | |
return o = null, function() { | |
var o = 2091639 * r + 2.3283064365386963e-10 * a; | |
return r = e, e = t, t = o - (a = 0 | o) | |
} | |
}(r) : Math.random, | |
this.p = n(e), | |
this.perm = new Uint8Array(512), | |
this.permMod12 = new Uint8Array(512); | |
for (var t = 0; t < 512; t++) | |
this.perm[t] = this.p[255 & t], | |
this.permMod12[t] = this.perm[t] % 12 | |
} | |
function n(r) { | |
var e, | |
t = new Uint8Array(256); | |
for (e = 0; e < 256; e++) | |
t[e] = e; | |
for (e = 0; e < 255; e++) { | |
var a = e + ~~(r() * (256 - e)), | |
o = t[e]; | |
t[e] = t[a], | |
t[a] = o | |
} | |
return t | |
} | |
i.prototype = { | |
grad3: new Float32Array([1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1, 0, 1, 0, 1, -1, 0, 1, 1, 0, -1, -1, 0, -1, 0, 1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1]), | |
grad4: new Float32Array([0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 1, 0, 1, 1, 1, 0, 1, -1, 1, 0, -1, 1, 1, 0, -1, -1, -1, 0, 1, 1, -1, 0, 1, -1, -1, 0, -1, 1, -1, 0, -1, -1, 1, 1, 0, 1, 1, 1, 0, -1, 1, -1, 0, 1, 1, -1, 0, -1, -1, 1, 0, 1, -1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, -1, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 0]), | |
noise2D: function(t, a) { | |
var o, | |
i, | |
n = this.permMod12, | |
f = this.perm, | |
s = this.grad3, | |
v = 0, | |
h = 0, | |
l = 0, | |
u = (t + a) * r, | |
d = Math.floor(t + u), | |
p = Math.floor(a + u), | |
M = (d + p) * e, | |
m = t - (d - M), | |
c = a - (p - M); | |
m > c ? (o = 1, i = 0) : (o = 0, i = 1); | |
var y = m - o + e, | |
w = c - i + e, | |
g = m - 1 + 2 * e, | |
A = c - 1 + 2 * e, | |
x = 255 & d, | |
q = 255 & p, | |
D = .5 - m * m - c * c; | |
if (D >= 0) { | |
var S = 3 * n[x + f[q]]; | |
v = (D *= D) * D * (s[S] * m + s[S + 1] * c) | |
} | |
var U = .5 - y * y - w * w; | |
if (U >= 0) { | |
var b = 3 * n[x + o + f[q + i]]; | |
h = (U *= U) * U * (s[b] * y + s[b + 1] * w) | |
} | |
var F = .5 - g * g - A * A; | |
if (F >= 0) { | |
var N = 3 * n[x + 1 + f[q + 1]]; | |
l = (F *= F) * F * (s[N] * g + s[N + 1] * A) | |
} | |
return 70 * (v + h + l) | |
}, | |
noise3D: function(r, e, a) { | |
var o, | |
i, | |
n, | |
f, | |
s, | |
v, | |
h, | |
l, | |
u, | |
d, | |
p = this.permMod12, | |
M = this.perm, | |
m = this.grad3, | |
c = (r + e + a) * (1 / 3), | |
y = Math.floor(r + c), | |
w = Math.floor(e + c), | |
g = Math.floor(a + c), | |
A = (y + w + g) * t, | |
x = r - (y - A), | |
q = e - (w - A), | |
D = a - (g - A); | |
x >= q ? q >= D ? (s = 1, v = 0, h = 0, l = 1, u = 1, d = 0) : x >= D ? (s = 1, v = 0, h = 0, l = 1, u = 0, d = 1) : (s = 0, v = 0, h = 1, l = 1, u = 0, d = 1) : q < D ? (s = 0, v = 0, h = 1, l = 0, u = 1, d = 1) : x < D ? (s = 0, v = 1, h = 0, l = 0, u = 1, d = 1) : (s = 0, v = 1, h = 0, l = 1, u = 1, d = 0); | |
var S = x - s + t, | |
U = q - v + t, | |
b = D - h + t, | |
F = x - l + 2 * t, | |
N = q - u + 2 * t, | |
C = D - d + 2 * t, | |
P = x - 1 + .5, | |
T = q - 1 + .5, | |
_ = D - 1 + .5, | |
j = 255 & y, | |
k = 255 & w, | |
z = 255 & g, | |
B = .6 - x * x - q * q - D * D; | |
if (B < 0) | |
o = 0; | |
else { | |
var E = 3 * p[j + M[k + M[z]]]; | |
o = (B *= B) * B * (m[E] * x + m[E + 1] * q + m[E + 2] * D) | |
} | |
var G = .6 - S * S - U * U - b * b; | |
if (G < 0) | |
i = 0; | |
else { | |
var H = 3 * p[j + s + M[k + v + M[z + h]]]; | |
i = (G *= G) * G * (m[H] * S + m[H + 1] * U + m[H + 2] * b) | |
} | |
var I = .6 - F * F - N * N - C * C; | |
if (I < 0) | |
n = 0; | |
else { | |
var J = 3 * p[j + l + M[k + u + M[z + d]]]; | |
n = (I *= I) * I * (m[J] * F + m[J + 1] * N + m[J + 2] * C) | |
} | |
var K = .6 - P * P - T * T - _ * _; | |
if (K < 0) | |
f = 0; | |
else { | |
var L = 3 * p[j + 1 + M[k + 1 + M[z + 1]]]; | |
f = (K *= K) * K * (m[L] * P + m[L + 1] * T + m[L + 2] * _) | |
} | |
return 32 * (o + i + n + f) | |
}, | |
noise4D: function(r, e, t, i) { | |
var n, | |
f, | |
s, | |
v, | |
h, | |
l, | |
u, | |
d, | |
p, | |
M, | |
m, | |
c, | |
y, | |
w, | |
g, | |
A, | |
x, | |
q = this.perm, | |
D = this.grad4, | |
S = (r + e + t + i) * a, | |
U = Math.floor(r + S), | |
b = Math.floor(e + S), | |
F = Math.floor(t + S), | |
N = Math.floor(i + S), | |
C = (U + b + F + N) * o, | |
P = r - (U - C), | |
T = e - (b - C), | |
_ = t - (F - C), | |
j = i - (N - C), | |
k = 0, | |
z = 0, | |
B = 0, | |
E = 0; | |
P > T ? k++ : z++, | |
P > _ ? k++ : B++, | |
P > j ? k++ : E++, | |
T > _ ? z++ : B++, | |
T > j ? z++ : E++, | |
_ > j ? B++ : E++; | |
var G = P - (l = k >= 3 ? 1 : 0) + o, | |
H = T - (u = z >= 3 ? 1 : 0) + o, | |
I = _ - (d = B >= 3 ? 1 : 0) + o, | |
J = j - (p = E >= 3 ? 1 : 0) + o, | |
K = P - (M = k >= 2 ? 1 : 0) + 2 * o, | |
L = T - (m = z >= 2 ? 1 : 0) + 2 * o, | |
O = _ - (c = B >= 2 ? 1 : 0) + 2 * o, | |
Q = j - (y = E >= 2 ? 1 : 0) + 2 * o, | |
R = P - (w = k >= 1 ? 1 : 0) + 3 * o, | |
V = T - (g = z >= 1 ? 1 : 0) + 3 * o, | |
W = _ - (A = B >= 1 ? 1 : 0) + 3 * o, | |
X = j - (x = E >= 1 ? 1 : 0) + 3 * o, | |
Y = P - 1 + 4 * o, | |
Z = T - 1 + 4 * o, | |
$ = _ - 1 + 4 * o, | |
rr = j - 1 + 4 * o, | |
er = 255 & U, | |
tr = 255 & b, | |
ar = 255 & F, | |
or = 255 & N, | |
ir = .6 - P * P - T * T - _ * _ - j * j; | |
if (ir < 0) | |
n = 0; | |
else { | |
var nr = q[er + q[tr + q[ar + q[or]]]] % 32 * 4; | |
n = (ir *= ir) * ir * (D[nr] * P + D[nr + 1] * T + D[nr + 2] * _ + D[nr + 3] * j) | |
} | |
var fr = .6 - G * G - H * H - I * I - J * J; | |
if (fr < 0) | |
f = 0; | |
else { | |
var sr = q[er + l + q[tr + u + q[ar + d + q[or + p]]]] % 32 * 4; | |
f = (fr *= fr) * fr * (D[sr] * G + D[sr + 1] * H + D[sr + 2] * I + D[sr + 3] * J) | |
} | |
var vr = .6 - K * K - L * L - O * O - Q * Q; | |
if (vr < 0) | |
s = 0; | |
else { | |
var hr = q[er + M + q[tr + m + q[ar + c + q[or + y]]]] % 32 * 4; | |
s = (vr *= vr) * vr * (D[hr] * K + D[hr + 1] * L + D[hr + 2] * O + D[hr + 3] * Q) | |
} | |
var lr = .6 - R * R - V * V - W * W - X * X; | |
if (lr < 0) | |
v = 0; | |
else { | |
var ur = q[er + w + q[tr + g + q[ar + A + q[or + x]]]] % 32 * 4; | |
v = (lr *= lr) * lr * (D[ur] * R + D[ur + 1] * V + D[ur + 2] * W + D[ur + 3] * X) | |
} | |
var dr = .6 - Y * Y - Z * Z - $ * $ - rr * rr; | |
if (dr < 0) | |
h = 0; | |
else { | |
var pr = q[er + 1 + q[tr + 1 + q[ar + 1 + q[or + 1]]]] % 32 * 4; | |
h = (dr *= dr) * dr * (D[pr] * Y + D[pr + 1] * Z + D[pr + 2] * $ + D[pr + 3] * rr) | |
} | |
return 27 * (n + f + s + v + h) | |
} | |
}, | |
i._buildPermutationTable = n, | |
"undefined" != typeof define && define.amd && define(function() { | |
return i | |
}), | |
"undefined" != typeof exports ? exports.SimplexNoise = i : "undefined" != typeof window && (window.SimplexNoise = i), | |
"undefined" != typeof module && (module.exports = i) | |
}(); | |
'use strict'; | |
// Particle properties | |
const particleCount = 700; | |
const particlePropCount = 9; | |
const particlePropsLength = particleCount * particlePropCount; | |
const rangeY = 100; | |
const baseTTL = 50; | |
const rangeTTL = 150; | |
const baseSpeed = 0.1; | |
const rangeSpeed = 2; | |
const baseRadius = 1; | |
const rangeRadius = 4; | |
const noiseSteps = 8; | |
const xOff = 0.00125; | |
const yOff = 0.00125; | |
const zOff = 0.0005; | |
const backgroundColor = 'hsla(260,40%,5%,1)'; | |
// New HSL values for teal and blue | |
const hueTeal = 159; | |
const hueBlue = 240; | |
let container; | |
let canvas; | |
let ctx; | |
let center; | |
let gradient; | |
let tick; | |
let simplex; | |
let particleProps; | |
let positions; | |
let velocities; | |
let lifeSpans; | |
let speeds; | |
let sizes; | |
let hues; | |
function setup() { | |
createCanvas(); | |
resize(); | |
initParticles(); | |
draw(); | |
} | |
function initParticles() { | |
tick = 0; | |
simplex = new SimplexNoise(); | |
particleProps = new Float32Array(particlePropsLength); | |
let i; | |
for (i = 0; i < particlePropsLength; i += particlePropCount) { | |
initParticle(i); | |
} | |
} | |
function initParticle(i) { | |
let x, y, vx, vy, life, ttl, speed, radius, hue; | |
x = rand(canvas.a.width); | |
y = center[1] + randRange(rangeY); | |
vx = 0; | |
vy = 0; | |
life = 0; | |
ttl = baseTTL + rand(rangeTTL); | |
speed = baseSpeed + rand(rangeSpeed); | |
radius = baseRadius + rand(rangeRadius); | |
// Assign either teal or blue hue randomly | |
hue = random() < 0.5 ? hueTeal : hueBlue; | |
particleProps.set([x, y, vx, vy, life, ttl, speed, radius, hue], i); | |
} | |
function drawParticles() { | |
let i; | |
for (i = 0; i < particlePropsLength; i += particlePropCount) { | |
updateParticle(i); | |
} | |
} | |
function updateParticle(i) { | |
let i2=1+i, i3=2+i, i4=3+i, i5=4+i, i6=5+i, i7=6+i, i8=7+i, i9=8+i; | |
let n, x, y, vx, vy, life, ttl, speed, x2, y2, radius, hue; | |
x = particleProps[i]; | |
y = particleProps[i2]; | |
n = simplex.noise3D(x * xOff, y * yOff, tick * zOff) * noiseSteps * TAU; | |
vx = lerp(particleProps[i3], cos(n), 0.5); | |
vy = lerp(particleProps[i4], sin(n), 0.5); | |
life = particleProps[i5]; | |
ttl = particleProps[i6]; | |
speed = particleProps[i7]; | |
x2 = x + vx * speed; | |
y2 = y + vy * speed; | |
radius = particleProps[i8]; | |
hue = particleProps[i9]; | |
drawParticle(x, y, x2, y2, life, ttl, radius, hue); | |
life++; | |
particleProps[i] = x2; | |
particleProps[i2] = y2; | |
particleProps[i3] = vx; | |
particleProps[i4] = vy; | |
particleProps[i5] = life; | |
(checkBounds(x, y) || life > ttl) && initParticle(i); | |
} | |
function drawParticle(x, y, x2, y2, life, ttl, radius, hue) { | |
ctx.a.save(); | |
ctx.a.lineCap = 'round'; | |
ctx.a.lineWidth = radius; | |
ctx.a.strokeStyle = `hsla(${hue},100%,60%,${fadeInOut(life, ttl)})`; | |
ctx.a.beginPath(); | |
ctx.a.moveTo(x, y); | |
ctx.a.lineTo(x2, y2); | |
ctx.a.stroke() | |
ctx.a.closePath(); | |
ctx.a.restore(); | |
} | |
function checkBounds(x, y) { | |
return( | |
x > canvas.a.width || | |
x < 0 || | |
y > canvas.a.height || | |
y < 0 | |
); | |
} | |
function createCanvas() { | |
container = document.querySelector('.content--canvas'); | |
canvas = { | |
a: document.createElement('canvas'), | |
b: document.createElement('canvas') | |
}; | |
canvas.b.style = ` | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
`; | |
container.appendChild(canvas.b); | |
ctx = { | |
a: canvas.a.getContext('2d'), | |
b: canvas.b.getContext('2d') | |
}; | |
center = []; | |
} | |
function resize() { | |
const { innerWidth, innerHeight } = window; | |
canvas.a.width = innerWidth; | |
canvas.a.height = innerHeight; | |
ctx.a.drawImage(canvas.b, 0, 0); | |
canvas.b.width = innerWidth; | |
canvas.b.height = innerHeight; | |
ctx.b.drawImage(canvas.a, 0, 0); | |
center[0] = 0.5 * canvas.a.width; | |
center[1] = 0.5 * canvas.a.height; | |
} | |
function renderGlow() { | |
ctx.b.save(); | |
ctx.b.filter = 'blur(8px) brightness(200%)'; | |
ctx.b.globalCompositeOperation = 'lighter'; | |
ctx.b.drawImage(canvas.a, 0, 0); | |
ctx.b.restore(); | |
ctx.b.save(); | |
ctx.b.filter = 'blur(4px) brightness(200%)'; | |
ctx.b.globalCompositeOperation = 'lighter'; | |
ctx.b.drawImage(canvas.a, 0, 0); | |
ctx.b.restore(); | |
} | |
function renderToScreen() { | |
ctx.b.save(); | |
ctx.b.globalCompositeOperation = 'lighter'; | |
ctx.b.drawImage(canvas.a, 0, 0); | |
ctx.b.restore(); | |
} | |
function draw() { | |
tick++; | |
ctx.a.clearRect(0, 0, canvas.a.width, canvas.a.height); | |
ctx.b.fillStyle = backgroundColor; | |
ctx.b.fillRect(0, 0, canvas.a.width, canvas.a.height); | |
drawParticles(); | |
renderGlow(); | |
renderToScreen(); | |
window.requestAnimationFrame(draw); | |
} | |
window.addEventListener('load', setup); | |
window.addEventListener('resize', resize); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment