PageSourceSearch

https://edmars.ai/script.js

js edmars.ai collected 2026-10-05 15:21:01 UTC 3,775 bytes, 114 lines download raw bytes

1(function () {
2  // ── Mars Globe ──
3  const canvas = document.getElementById('mars-canvas');
4  const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true });
5  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
6
7  const scene = new THREE.Scene();
8  const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
9  camera.position.z = 2.8;
10
11  // Sphere
12  const geo = new THREE.SphereGeometry(1, 64, 64);
13
14  // Procedural Mars texture using canvas
15  const texCanvas = document.createElement('canvas');
16  texCanvas.width = 512; texCanvas.height = 256;
17  const ctx = texCanvas.getContext('2d');
18
19  // Base color
20  const grad = ctx.createLinearGradient(0, 0, 512, 256);
21  grad.addColorStop(0,   '#7a2a10');
22  grad.addColorStop(0.3, '#a33a18');
23  grad.addColorStop(0.6, '#8b3012');
24  grad.addColorStop(1,   '#6a2208');
25  ctx.fillStyle = grad;
26  ctx.fillRect(0, 0, 512, 256);
27
28  // Add noise-like craters / terrain
29  for (let i = 0; i < 800; i++) {
30    const x = Math.random() * 512;
31    const y = Math.random() * 256;
32    const r = Math.random() * 18 + 1;
33    const brightness = Math.random() > 0.5 ? 1.15 : 0.82;
34    const cg = ctx.createRadialGradient(x, y, 0, x, y, r);
35    const base = 'rgba(' + Math.floor(140*brightness) + ',' + Math.floor(50*brightness) + ',' + Math.floor(20*brightness);
36    cg.addColorStop(0, base + ',0.45)');
37    cg.addColorStop(1, base + ',0)');
38    ctx.fillStyle = cg;
39    ctx.beginPath(); ctx.arc(x, y, r, 0, Math.PI * 2); ctx.fill();
40  }
41
42  const texture = new THREE.CanvasTexture(texCanvas);
43  const mat = new THREE.MeshStandardMaterial({
44    map: texture,
45    roughness: 0.85,
46    metalness: 0.05,
47  });
48  const sphere = new THREE.Mesh(geo, mat);
49  sphere.position.set(3.2, -0.3, -1);
50  scene.add(sphere);
51
52  // Atmosphere glow
53  const atmGeo = new THREE.SphereGeometry(1.06, 32, 32);
54  const atmMat = new THREE.MeshBasicMaterial({
55    color: new THREE.Color('#c8451a'),
56    transparent: true,
57    opacity: 0.08,
58    side: THREE.BackSide,
59  });
60  const atm = new THREE.Mesh(atmGeo, atmMat);
61  atm.position.copy(sphere.position);
62  scene.add(atm);
63
64  // Stars
65  const starGeo = new THREE.BufferGeometry();
66  const starCount = 1200;
67  const positions = new Float32Array(starCount * 3);
68  for (let i = 0; i < starCount * 3; i++) {
69    positions[i] = (Math.random() - 0.5) * 80;
70  }
71  starGeo.setAttribute('position', new THREE.BufferAttribute(positions, 3));
72  const starMat = new THREE.PointsMaterial({ color: 0xffffff, size: 0.04 });
73  scene.add(new THREE.Points(starGeo, starMat));
74
75  // Lights
76  scene.add(new THREE.AmbientLight(0xffffff, 0.18));
77  const sun = new THREE.DirectionalLight(0xffddbb, 1.4);
78  sun.position.set(5, 2, 4);
79  scene.add(sun);
80
81  // Resize
82  function resize() {
83    const w = canvas.clientWidth, h = canvas.clientHeight;
84    renderer.setSize(w, h, false);
85    camera.aspect = w / h;
86    camera.updateProjectionMatrix();
87  }
88  window.addEventListener('resize', resize);
89  resize();
90
91  // Mouse parallax
92  let mx = 0, my = 0;
93  window.addEventListener('mousemove', function (e) {
94    mx = (e.clientX / window.innerWidth - 0.5) * 0.04;
95    my = (e.clientY / window.innerHeight - 0.5) * 0.02;
96  });
97
98  let t = 0;
99  (function animate() {
100    requestAnimationFrame(animate);
101    t += 0.004;
102    sphere.rotation.y = t;
103    sphere.position.x = 3.2 + mx;
104    sphere.position.y = -0.3 + my;
105    atm.position.copy(sphere.position);
106    renderer.render(scene, camera);
107  })();
108
109  // ── Scroll reveal ──
110  var observer = new IntersectionObserver(function (entries) {
111    entries.forEach(function (e) { if (e.isIntersecting) { e.target.classList.add('visible'); } });
112  }, { threshold: 0.1 });
113  document.querySelectorAll('.reveal').forEach(function (el) { observer.observe(el); });
114})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.