Загрузка...

Полноэкранный hero-блок с анимированными WebGL-волокнами (Three.js) и sci-fi UI. Идеален для лендингов по данным, AI, визуализации.
<section class="relative w-full h-screen bg-[#050505] overflow-hidden flex items-center justify-center"
style="font-family: 'Inter', sans-serif;">
<!-- Background Canvas Container -->
<div id="strands-container" class="absolute inset-0 z-0">
<canvas id="webgl-canvas" class="w-full h-full"></canvas>
</div>
<!-- UI Overlay Layer -->
<div class="relative z-10 w-full max-w-7xl mx-auto px-8 flex flex-col pointer-events-none">
<div class="flex justify-between items-start mb-32">
<div class="flex flex-col gap-2">
<div class="flex items-center gap-3">
<span class="w-2 h-2 bg-white rounded-full animate-pulse"></span>
<span style="font-family: 'Space Mono', monospace;" class="text-[10px] text-white/50 tracking-[0.3em] uppercase">Strand Synthesis Active</span>
</div>
<h1 class="text-6xl md:text-8xl font-light text-white tracking-tighter leading-none">
Neural<br><span class="opacity-40 italic">Fibers.</span>
</h1>
</div>
<div style="font-family: 'Space Mono', monospace;" class="hidden md:block text-right">
<div class="text-white/40 text-[10px] uppercase mb-4 tracking-widest">Global Connection Map</div>
<div class="flex flex-col gap-1 text-[10px] text-white/80">
<span>LATENCY: 4.2ms</span>
<span>DENSITY: 84%</span>
<span>FLUX: CONSTANT</span>
</div>
</div>
</div>
<div class="mt-auto border-l border-white/10 pl-6 py-4">
<p class="max-w-xs text-white/40 text-sm leading-relaxed mb-6">
Visualizing the flow of unstructured data as it crystallizes into cognitive strands. Each curve represents a
persistent memory thread.
</p>
<div class="flex gap-4 pointer-events-auto">
<button class="px-6 py-2 border border-white/20 text-white text-[10px] uppercase tracking-widest hover:bg-white hover:text-black transition-all duration-300" style="font-family: 'Space Mono', monospace;">
Adjust Tension
</button>
<button class="px-6 py-2 bg-white text-black text-[10px] uppercase tracking-widest hover:bg-opacity-80 transition-all duration-300" style="font-family: 'Space Mono', monospace;">
Freeze Frame
</button>
</div>
</div>
</div>
<!-- Corner Brackets -->
<div class="absolute top-8 left-8 w-12 h-12 border-t border-l border-white/20 pointer-events-none"></div>
<div class="absolute top-8 right-8 w-12 h-12 border-t border-r border-white/20 pointer-events-none"></div>
<div class="absolute bottom-8 left-8 w-12 h-12 border-b border-l border-white/20 pointer-events-none"></div>
<div class="absolute bottom-8 right-8 w-12 h-12 border-b border-r border-white/20 pointer-events-none"></div>
<!-- WebGL Logic -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
(function() {
const canvas = document.getElementById('webgl-canvas');
const container = document.getElementById('strands-container');
let width = container.clientWidth;
let height = container.clientHeight;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
camera.position.z = 30;
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true,
alpha: true
});
renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
const strands = [];
const strandCount = 40;
const pointsPerStrand = 50;
for (let i = 0; i < strandCount; i++) {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(pointsPerStrand * 3);
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.LineBasicMaterial({
color: 0xffffff,
transparent: true,
opacity: Math.random() * 0.4 + 0.1,
blending: THREE.AdditiveBlending
});
const line = new THREE.Line(geometry, material);
// Meta data for animation
line.userData = {
offset: Math.random() * 100,
speed: 0.005 + Math.random() * 0.01,
amplitude: 2 + Math.random() * 5,
radius: 5 + Math.random() * 15,
phase: Math.random() * Math.PI * 2
};
scene.add(line);
strands.push(line);
}
let time = 0;
function animate() {
requestAnimationFrame(animate);
time += 0.01;
strands.forEach((strand, sIdx) => {
const positions = strand.geometry.attributes.position.array;
const { offset, speed, amplitude, radius, phase } = strand.userData;
for (let i = 0; i < pointsPerStrand; i++) {
const t = i / pointsPerStrand;
const angle = t * Math.PI * 2 + (time * speed * 10);
// Wave physics for the strands
const x = Math.cos(angle + phase) * radius + Math.sin(time + sIdx) * 2;
const y = (t - 0.5) * 60 + Math.sin(time * speed + t * 5 + offset) * amplitude;
const z = Math.sin(angle + phase) * radius + Math.cos(time + sIdx) * 2;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
}
strand.geometry.attributes.position.needsUpdate = true;
strand.rotation.y += 0.001;
});
renderer.render(scene, camera);
}
function onResize() {
width = container.clientWidth;
height = container.clientHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
window.addEventListener('resize', onResize);
animate();
})();
</script>
</section>