|
11 | 11 | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"> |
12 | 12 | <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> |
13 | 13 | <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> |
| 14 | + <!-- Three.js for 3D background --> |
| 15 | + <script type="importmap"> |
| 16 | + { |
| 17 | + "imports": { |
| 18 | + "three": "https://unpkg.com/three@0.128.0/build/three.module.js" |
| 19 | + } |
| 20 | + } |
| 21 | + </script> |
14 | 22 | <style> |
15 | 23 | /* ========== GLOBAL STYLES – BLACKSITE POLISH ========== */ |
16 | 24 | * { margin: 0; padding: 0; box-sizing: border-box; } |
|
46 | 54 | position: relative; |
47 | 55 | } |
48 | 56 |
|
49 | | - /* Background Canvas */ |
| 57 | + /* 3D Canvas (background) */ |
50 | 58 | #bg-canvas { |
51 | 59 | position: fixed; |
52 | 60 | top: 0; |
@@ -982,61 +990,75 @@ <h4>Results</h4> |
982 | 990 | </div> |
983 | 991 | </div> |
984 | 992 |
|
| 993 | +<script type="module"> |
| 994 | + import * as THREE from 'three'; |
| 995 | + |
| 996 | + // ========== THREE.JS BACKGROUND ========== |
| 997 | + const canvas = document.getElementById('bg-canvas'); |
| 998 | + const renderer = new THREE.WebGLRenderer({ canvas, alpha: true }); |
| 999 | + renderer.setSize(window.innerWidth, window.innerHeight); |
| 1000 | + renderer.setClearColor(0x000000, 0); // transparent |
| 1001 | + |
| 1002 | + const scene = new THREE.Scene(); |
| 1003 | + const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); |
| 1004 | + camera.position.z = 15; |
| 1005 | + |
| 1006 | + // Starfield (points) |
| 1007 | + const starGeometry = new THREE.BufferGeometry(); |
| 1008 | + const starCount = 2000; |
| 1009 | + const starPositions = new Float32Array(starCount * 3); |
| 1010 | + for (let i = 0; i < starCount; i++) { |
| 1011 | + starPositions[i*3] = (Math.random() - 0.5) * 2000; |
| 1012 | + starPositions[i*3+1] = (Math.random() - 0.5) * 2000; |
| 1013 | + starPositions[i*3+2] = (Math.random() - 0.5) * 500; |
| 1014 | + } |
| 1015 | + starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3)); |
| 1016 | + const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.5, transparent: true, opacity: 0.8 }); |
| 1017 | + const stars = new THREE.Points(starGeometry, starMaterial); |
| 1018 | + scene.add(stars); |
| 1019 | + |
| 1020 | + // Orbital ring |
| 1021 | + const ringGeometry = new THREE.TorusGeometry(4.5, 0.08, 64, 300); |
| 1022 | + const ringMaterial = new THREE.MeshBasicMaterial({ color: 0xc9a028, transparent: true, opacity: 0.4 }); |
| 1023 | + const ring = new THREE.Mesh(ringGeometry, ringMaterial); |
| 1024 | + scene.add(ring); |
| 1025 | + |
| 1026 | + // Floating particles (small spheres) |
| 1027 | + const particleCount = 300; |
| 1028 | + const particleGeometry = new THREE.BufferGeometry(); |
| 1029 | + const particlePositions = new Float32Array(particleCount * 3); |
| 1030 | + for (let i = 0; i < particleCount; i++) { |
| 1031 | + particlePositions[i*3] = (Math.random() - 0.5) * 30; |
| 1032 | + particlePositions[i*3+1] = (Math.random() - 0.5) * 20; |
| 1033 | + particlePositions[i*3+2] = (Math.random() - 0.5) * 20; |
| 1034 | + } |
| 1035 | + particleGeometry.setAttribute('position', new THREE.BufferAttribute(particlePositions, 3)); |
| 1036 | + const particleMaterial = new THREE.PointsMaterial({ color: 0xffaa33, size: 0.08, transparent: true, opacity: 0.3 }); |
| 1037 | + const particles = new THREE.Points(particleGeometry, particleMaterial); |
| 1038 | + scene.add(particles); |
| 1039 | + |
| 1040 | + function animate() { |
| 1041 | + requestAnimationFrame(animate); |
| 1042 | + stars.rotation.y += 0.0005; |
| 1043 | + stars.rotation.x += 0.0003; |
| 1044 | + ring.rotation.x += 0.003; |
| 1045 | + ring.rotation.z += 0.002; |
| 1046 | + particles.rotation.y += 0.001; |
| 1047 | + particles.rotation.x += 0.0005; |
| 1048 | + renderer.render(scene, camera); |
| 1049 | + } |
| 1050 | + animate(); |
| 1051 | + |
| 1052 | + window.addEventListener('resize', onWindowResize, false); |
| 1053 | + function onWindowResize() { |
| 1054 | + camera.aspect = window.innerWidth / window.innerHeight; |
| 1055 | + camera.updateProjectionMatrix(); |
| 1056 | + renderer.setSize(window.innerWidth, window.innerHeight); |
| 1057 | + } |
| 1058 | +</script> |
| 1059 | + |
985 | 1060 | <script> |
986 | 1061 | (function() { |
987 | | - // ---------- BACKGROUND (particle canvas) ---------- |
988 | | - const canvas = document.getElementById('bg-canvas'); |
989 | | - const ctx = canvas.getContext('2d'); |
990 | | - let width, height, animFrame; |
991 | | - let particles = []; |
992 | | - const PARTICLE_COUNT = 120; |
993 | | - |
994 | | - function resize() { |
995 | | - width = window.innerWidth; |
996 | | - height = window.innerHeight; |
997 | | - canvas.width = width; |
998 | | - canvas.height = height; |
999 | | - } |
1000 | | - |
1001 | | - function initParticles() { |
1002 | | - particles = []; |
1003 | | - for (let i = 0; i < PARTICLE_COUNT; i++) { |
1004 | | - particles.push({ |
1005 | | - x: Math.random() * width, |
1006 | | - y: Math.random() * height, |
1007 | | - radius: 1 + Math.random() * 2, |
1008 | | - alpha: 0.3 + Math.random() * 0.5, |
1009 | | - speed: 0.2 + Math.random() * 0.8, |
1010 | | - }); |
1011 | | - } |
1012 | | - } |
1013 | | - |
1014 | | - function draw() { |
1015 | | - ctx.clearRect(0, 0, width, height); |
1016 | | - ctx.fillStyle = '#050508'; |
1017 | | - ctx.fillRect(0, 0, width, height); |
1018 | | - for (let p of particles) { |
1019 | | - ctx.beginPath(); |
1020 | | - ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2); |
1021 | | - ctx.fillStyle = `rgba(201, 160, 40, ${p.alpha})`; |
1022 | | - ctx.fill(); |
1023 | | - p.y += p.speed; |
1024 | | - if (p.y > height) p.y = 0; |
1025 | | - } |
1026 | | - animFrame = requestAnimationFrame(draw); |
1027 | | - } |
1028 | | - |
1029 | | - function startBackground() { |
1030 | | - resize(); |
1031 | | - initParticles(); |
1032 | | - draw(); |
1033 | | - window.addEventListener('resize', () => { |
1034 | | - resize(); |
1035 | | - initParticles(); |
1036 | | - }); |
1037 | | - } |
1038 | | - startBackground(); |
1039 | | - |
1040 | 1062 | // ---------- CUSTOM CURSOR ---------- |
1041 | 1063 | const cursor = document.getElementById('custom-cursor'); |
1042 | 1064 | if (cursor) { |
|
0 commit comments