Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions satellite.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>EcoPulse | Satellite View</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

<style>
body { margin:0; overflow:hidden; background:#000; }
#tooltip {
position:absolute;
background:rgba(0,0,0,0.8);
color:#fff;
padding:8px 12px;
border-radius:6px;
font-size:14px;
pointer-events:none;
display:none;
}
</style>
</head>

<body>

<!-- Top Bar -->
<div class="absolute top-0 left-0 w-full bg-black bg-opacity-60 p-4 flex justify-between items-center text-white z-10">
<h1 class="text-xl font-bold text-green-400">Satellite Pollution View 🛰</h1>
<a href="index.html" class="bg-blue-500 px-4 py-2 rounded hover:bg-purple-600 transition">
⬅ Back Home
</a>
</div>

<div id="tooltip"></div>

<script>

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias:true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

camera.position.z = 5;

// STARFIELD
const starGeometry = new THREE.BufferGeometry();
const starVertices = [];
for (let i = 0; i < 10000; i++) {
starVertices.push(
THREE.MathUtils.randFloatSpread(2000),
THREE.MathUtils.randFloatSpread(2000),
THREE.MathUtils.randFloatSpread(2000)
);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices,3));
const starMaterial = new THREE.PointsMaterial({ color:0xffffff });
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);

// EARTH
const earthGeometry = new THREE.SphereGeometry(2, 64, 64);
const textureLoader = new THREE.TextureLoader();
const earthTexture = textureLoader.load("https://threejs.org/examples/textures/earth_atmos_2048.jpg");

const earthMaterial = new THREE.MeshStandardMaterial({ map:earthTexture });
const earth = new THREE.Mesh(earthGeometry, earthMaterial);
scene.add(earth);

// ATMOSPHERE GLOW
const atmosphereGeometry = new THREE.SphereGeometry(2.1,64,64);
const atmosphereMaterial = new THREE.MeshBasicMaterial({
color:0x3B82F6,
transparent:true,
opacity:0.2
});
const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial);
scene.add(atmosphere);

// LIGHTS
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
directionalLight.position.set(5,3,5);
scene.add(directionalLight);

// DATA
const cities = [
{ name:"Delhi", lat:28.6, lon:77.2, level:"Severe", color:0xff0000 },
{ name:"Mumbai", lat:19.0, lon:72.8, level:"High", color:0xff8800 },
{ name:"Bangalore", lat:12.9, lon:77.6, level:"Moderate", color:0xffff00 },
{ name:"Chennai", lat:13.0, lon:80.2, level:"Low", color:0x00ff00 }
];

function latLonToVector3(lat, lon, radius) {
const phi = (90-lat)*(Math.PI/180);
const theta = (lon+180)*(Math.PI/180);
const x = -(radius*Math.sin(phi)*Math.cos(theta));
const z = (radius*Math.sin(phi)*Math.sin(theta));
const y = (radius*Math.cos(phi));
return new THREE.Vector3(x,y,z);
}

const markerGeometry = new THREE.SphereGeometry(0.08,16,16);
const markers = [];

cities.forEach(city=>{
const material = new THREE.MeshBasicMaterial({ color:city.color });
const marker = new THREE.Mesh(markerGeometry, material);
marker.position.copy(latLonToVector3(city.lat, city.lon, 2.15));
marker.userData = city;
scene.add(marker);
markers.push(marker);
});

// RAYCASTER
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const tooltip = document.getElementById("tooltip");

window.addEventListener("mousemove", e=>{
mouse.x = (e.clientX/window.innerWidth)*2-1;
mouse.y = -(e.clientY/window.innerHeight)*2+1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(markers);
if(intersects.length>0){
const city = intersects[0].object.userData;
tooltip.style.display="block";
tooltip.style.left=e.clientX+10+"px";
tooltip.style.top=e.clientY+10+"px";
tooltip.innerHTML=`<strong>${city.name}</strong><br>Level: ${city.level}`;
} else {
tooltip.style.display="none";
}
});

// ANIMATION
function animate(){
requestAnimationFrame(animate);
earth.rotation.y += 0.002;
atmosphere.rotation.y += 0.002;
renderer.render(scene,camera);
}
animate();

// RESIZE
window.addEventListener("resize", ()=>{
camera.aspect=window.innerWidth/window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
});

</script>

</body>
</html>
Loading