data_flow_static / main.js
WebashalarForML's picture
Upload 2 files
8545876 verified
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const config = {
pointCount: 800,
radius: 2,
pulseSpeed: 1.2,
amplitude: 0.5,
color: {
primary: [0.5, 0.3, 1.0], // Purple
secondary: [0.8, 0.2, 1.0], // Pink
accent: [0.3, 0.5, 1.0] // Blue
}
};
let scene, camera, renderer, controls;
let pointCloud, particles;
let clock;
init();
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0d0d2b);
const canvas = document.querySelector('#webgl');
renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
50
);
camera.position.set(0, 0, 5);
controls = new OrbitControls(camera, canvas);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
createParticles();
setupLighting();
setupEventListeners();
}
function createParticles() {
const positions = new Float32Array(config.pointCount * 3);
const colors = new Float32Array(config.pointCount * 3);
const sizes = new Float32Array(config.pointCount);
particles = {
positions: new Float32Array(config.pointCount),
targetPositions: new Float32Array(config.pointCount),
speeds: new Float32Array(config.pointCount),
phases: new Float32Array(config.pointCount)
};
for (let i = 0; i < config.pointCount; i++) {
const index = i * 3;
const phi = Math.acos(-1 + (2 * i) / config.pointCount);
const theta = Math.sqrt(config.pointCount * Math.PI) * phi;
const x = config.radius * Math.sin(phi) * Math.cos(theta);
const y = config.radius * Math.sin(phi) * Math.sin(theta);
const z = config.radius * Math.cos(phi);
positions[index] = x;
positions[index + 1] = y;
positions[index + 2] = z;
const dist = Math.sqrt(x * x + y * y + z * z) / config.radius;
const r = THREE.MathUtils.lerp(config.color.primary[0], config.color.accent[0], dist);
const g = THREE.MathUtils.lerp(config.color.primary[1], config.color.secondary[1], dist);
const b = THREE.MathUtils.lerp(config.color.primary[2], 1.0, dist);
colors[index] = r;
colors[index + 1] = g;
colors[index + 2] = b;
sizes[i] = Math.random() * 0.1 + 0.05;
particles.positions[i] = 0;
particles.targetPositions[i] = 0;
particles.speeds[i] = Math.random() * 0.5 + 0.5;
particles.phases[i] = Math.random() * Math.PI * 2;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 0.1,
vertexColors: true,
sizeAttenuation: true,
transparent: true,
opacity: 0.9,
blending: THREE.AdditiveBlending
});
pointCloud = new THREE.Points(geometry, material);
scene.add(pointCloud);
clock = new THREE.Clock();
scheduleNextPulse();
}
function setupLighting() {
const ambientLight = new THREE.AmbientLight(0x404060, 0.5);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0x7f5af0, 1, 10);
pointLight.position.set(2, 3, 4);
scene.add(pointLight);
}
function setupEventListeners() {
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
}
function scheduleNextPulse() {
const pulseDelay = Math.random() * 3000 + 1500;
setTimeout(() => {
triggerPulse();
}, pulseDelay);
}
function triggerPulse() {
const waveCenter = Math.floor(Math.random() * config.pointCount);
const positions = pointCloud.geometry.attributes.position.array;
for (let i = 0; i < config.pointCount; i++) {
const index = i * 3;
const x = positions[index];
const y = positions[index + 1];
const z = positions[index + 2];
const distToCenter = Math.sqrt(
(x - positions[waveCenter * 3]) ** 2 +
(y - positions[waveCenter * 3 + 1]) ** 2 +
(z - positions[waveCenter * 3 + 2]) ** 2
);
const normalizedDist = distToCenter / (config.radius * 2);
const waveFactor = 1 - Math.min(Math.max(normalizedDist, 0), 1);
particles.targetPositions[i] = config.amplitude * waveFactor;
}
scheduleNextPulse();
}
function updateParticles(delta) {
const positions = pointCloud.geometry.attributes.position.array;
const originalPositions = new Float32Array(positions);
for (let i = 0; i < config.pointCount; i++) {
const index = i * 3;
particles.positions[i] += (particles.targetPositions[i] - particles.positions[i]) * delta * particles.speeds[i];
const pulseEffect = particles.positions[i] * Math.sin(clock.getElapsedTime() * particles.speeds[i] + particles.phases[i]);
const displacement = pulseEffect;
positions[index] = originalPositions[index] * (1 + displacement);
positions[index + 1] = originalPositions[index + 1] * (1 + displacement);
positions[index + 2] = originalPositions[index + 2] * (1 + displacement);
particles.targetPositions[i] *= 0.95;
}
pointCloud.geometry.attributes.position.needsUpdate = true;
}
function animate() {
const delta = Math.min(clock.getDelta(), 0.1);
controls.update();
updateParticles(delta);
renderer.render(scene, camera);
requestAnimationFrame(animate);
}