Contra-Signal / frontend /static /js /landing.js
GSMSB's picture
deploy: fresh start with clean history
a78209f
Raw
History Blame Contribute Delete
6.03 kB
document.addEventListener('DOMContentLoaded', () => {
// --- 1. ANIMATION SETUP (GSAP) ---
// Custom "SplitText" implementation for letters/lines since we don't have the plugin
const h1 = document.getElementById('hero-title');
const p = document.getElementById('hero-desc');
const ctas = document.getElementById('hero-ctas');
const bgContainer = document.getElementById('canvas-container');
// Helper to wrap lines/words (Simple version: just treat whole block for now to ensure smoothness,
// or split by words if user wants granulatiry. Let's do simple fade up for stability).
// Initial States
gsap.set(bgContainer, { filter: "blur(28px)" });
gsap.set([h1, p, ctas], { opacity: 0, y: 24, filter: "blur(8px)" });
// Timeline
const tl = gsap.timeline({ defaults: { ease: "power2.out" } });
tl.to(bgContainer, { filter: "blur(0px)", duration: 1.5 }, 0)
.to(h1, { opacity: 1, y: 0, filter: "blur(0px)", duration: 1 }, 0.3)
.to(p, { opacity: 1, y: 0, filter: "blur(0px)", duration: 1 }, 0.5)
.to(ctas, { opacity: 1, y: 0, filter: "blur(0px)", duration: 0.8 }, 0.7);
// --- 2. THREE.JS SHADER SETUP ---
const container = document.getElementById('canvas-container');
// Scence Setup
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
camera.position.z = 1;
const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
// Shader Code (Ported from React component)
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 1.0);
}
`;
const fragmentShader = `
precision highp float;
varying vec2 vUv;
uniform float u_time;
uniform vec3 u_resolution;
#define STEP 256
#define EPS .001
float smin( float a, float b, float k ) {
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
const mat2 m = mat2(.8,.6,-.6,.8);
float noise( in vec2 x ) {
return sin(1.5*x.x)*sin(1.5*x.y);
}
float fbm6( vec2 p ) {
float f = 0.0;
f += 0.500000*(0.5+0.5*noise( p )); p = m*p*2.02;
f += 0.250000*(0.5+0.5*noise( p )); p = m*p*2.03;
f += 0.125000*(0.5+0.5*noise( p )); p = m*p*2.01;
f += 0.062500*(0.5+0.5*noise( p )); p = m*p*2.04;
f += 0.015625*(0.5+0.5*noise( p ));
return f/0.96875;
}
mat2 getRot(float a) {
float sa = sin(a), ca = cos(a);
return mat2(ca,-sa,sa,ca);
}
vec3 _position;
float sphere(vec3 center, float radius) {
return distance(_position,center) - radius;
}
float swingPlane(float height) {
vec3 pos = _position + vec3(0.,0.,u_time * 5.5);
float def = fbm6(pos.xz * .25) * 0.5;
float way = pow(abs(pos.x) * 34. ,2.5) *.0000125;
def *= way;
float ch = height + def;
return max(pos.y - ch,0.);
}
float map(vec3 pos) {
_position = pos;
float dist;
dist = swingPlane(0.);
float sminFactor = 5.25;
dist = smin(dist,sphere(vec3(0.,-15.,80.),60.),sminFactor);
return dist;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
vec2 uv = (fragCoord.xy-.5*u_resolution.xy)/u_resolution.y;
vec3 rayOrigin = vec3(uv + vec2(0.,6.), -1. );
vec3 rayDir = normalize(vec3(uv , 1.));
rayDir.zy = getRot(.15) * rayDir.zy;
vec3 position = rayOrigin;
float curDist;
int nbStep = 0;
for(int i = 0; i < STEP; i++) {
// Approximate texture fetch simply as noise or remove if unneeded
// The original code had texture(iChannel0...) which we don't have.
// We'll skip the texture displacement for simplicity in vanilla port
// or replicate with simple noise if needed.
// Simplified raymarching step:
curDist = map(position);
if(curDist < EPS) break;
position += rayDir * curDist * .5;
nbStep++;
}
float f;
float dist = distance(rayOrigin,position);
f = dist /(98.);
f = float(nbStep) / float(STEP);
f *= .9;
vec3 col = vec3(f);
fragColor = vec4(col,1.0);
}
void main() {
mainImage(gl_FragColor, vUv * u_resolution.xy);
}
`;
// Uniforms
const uniforms = {
u_time: { value: 0 },
u_resolution: { value: new THREE.Vector3(window.innerWidth, window.innerHeight, 1) }
};
// Mesh
const geometry = new THREE.PlaneGeometry(2, 2);
const material = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// Resize Handler
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
uniforms.u_resolution.value.set(window.innerWidth, window.innerHeight, 1);
});
// Animation Loop
const clock = new THREE.Clock(); // Use THREE clock for u_time
function animate() {
requestAnimationFrame(animate);
uniforms.u_time.value = clock.getElapsedTime() * 0.5; // Match React's * 0.5
renderer.render(scene, camera);
}
animate();
});