asigalov61 commited on
Commit
a68ed56
·
verified ·
1 Parent(s): 248ae6d

Update stars.js

Browse files
Files changed (1) hide show
  1. stars.js +88 -95
stars.js CHANGED
@@ -1,96 +1,115 @@
1
- // Enhanced Starfield – Script Only
2
 
3
  (() => {
4
  const canvas = document.getElementById("starfield");
5
  const ctx = canvas.getContext("2d");
6
- let dpr = window.devicePixelRatio || 1;
7
- let width, height;
8
- let speedFactor = 1;
9
- let starLayers = [];
10
  let comets = [];
11
- let pulses = [];
12
 
13
- // Configuration for 3 parallax star layers
14
- const layersConfig = [
15
- { count: 600, speed: 0.4, size: 1.2 },
16
- { count: 400, speed: 0.8, size: 2.0 },
17
- { count: 200, speed: 1.6, size: 3.0 },
18
  ];
19
 
20
  // Utility
21
  const rand = (min, max) => min + Math.random() * (max - min);
22
 
23
- // Resize & DPR handling
24
  function resize() {
25
- dpr = window.devicePixelRatio || 1;
26
  width = window.innerWidth;
27
  height = window.innerHeight;
28
- canvas.width = width * dpr;
29
- canvas.height = height * dpr;
30
- ctx.scale(dpr, dpr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
  // Initialize star layers
34
  function initStars() {
35
- starLayers = layersConfig.map(cfg => {
36
  const stars = [];
37
  for (let i = 0; i < cfg.count; i++) {
38
  stars.push({
39
  x: rand(-width / 2, width / 2),
40
  y: rand(-height / 2, height / 2),
41
  z: rand(1, width),
42
- baseA: rand(0.3, 1),
43
- hue: rand(200, 260),
44
  });
45
  }
46
  return { ...cfg, stars };
47
  });
48
  }
49
 
50
- // Spawn comets occasionally
51
  function maybeComet() {
52
- if (Math.random() < 0.004) {
53
  comets.push({
54
  x: rand(0, width),
55
  y: rand(0, height * 0.2),
56
  len: 0,
57
- maxLen: rand(120, 280),
58
  angle: Math.PI * 0.25 + rand(-0.2, 0.2),
59
- speed: rand(6, 14),
60
  });
61
  }
62
  }
63
 
64
- // On click, create a warp pulse
65
- canvas.addEventListener("click", e => {
66
- pulses.push({
67
- x: e.clientX,
68
- y: e.clientY,
69
- r: 0,
70
- maxR: Math.hypot(width, height),
71
- alpha: 0.6
72
- });
73
- });
74
-
75
- // Mouse-based speed control
76
  window.addEventListener("mousemove", e => {
77
- speedFactor = 0.5 + (e.clientX / width) * 2.5;
78
  });
79
 
80
- // Update positions, twinkle, comets, pulses
81
  function update() {
82
- starLayers.forEach(layer => {
 
83
  layer.stars.forEach(s => {
84
- s.z -= layer.speed * speedFactor;
85
  if (s.z <= 0) {
86
  s.z = width;
87
  s.x = rand(-width / 2, width / 2);
88
  s.y = rand(-height / 2, height / 2);
89
- s.baseA = rand(0.3, 1);
90
- s.hue = rand(200, 260);
91
  }
92
- // twinkle
93
- s.a = s.baseA + Math.sin((Date.now() % 10000) / 10000 * Math.PI * 2) * 0.3;
 
94
  });
95
  });
96
 
@@ -101,61 +120,46 @@
101
  c.y += Math.sin(c.angle) * c.speed;
102
  });
103
 
104
- pulses = pulses.filter(p => p.alpha > 0);
105
- pulses.forEach(p => {
106
- p.r += 30;
107
- p.alpha -= 0.008;
108
- });
109
-
110
  maybeComet();
111
  }
112
 
113
- // Draw frame
114
  function draw() {
115
- // 1) motion trails
116
- ctx.fillStyle = "rgba(0,0,0,0.3)";
117
- ctx.fillRect(0, 0, width, height);
118
 
119
- // 2) vignette
120
- const vig = ctx.createRadialGradient(
121
- width / 2, height / 2, width / 3,
122
- width / 2, height / 2, width / 1.2
123
- );
124
- vig.addColorStop(0, "rgba(0,0,0,0)");
125
- vig.addColorStop(1, "rgba(0,0,0,0.7)");
126
- ctx.fillStyle = vig;
127
  ctx.fillRect(0, 0, width, height);
128
 
129
- // 3) stars additive glow
130
- ctx.globalCompositeOperation = "lighter";
131
- starLayers.forEach(layer => {
132
- layer.stars.forEach(s => {
 
 
133
  const k = (width / 2) / s.z;
134
  const x = s.x * k + width / 2;
135
  const y = s.y * k + height / 2;
136
  if (x < 0 || x > width || y < 0 || y > height) return;
137
-
138
- const size = layer.size * (1 - s.z / width) * 2;
139
- ctx.save();
140
- ctx.translate(x, y);
141
- ctx.fillStyle = `hsla(${s.hue}, 80%, 90%, ${s.a})`;
142
- ctx.shadowColor = `hsla(${s.hue}, 100%, 80%, ${s.a})`;
143
- ctx.shadowBlur = size * 2.5;
144
- ctx.beginPath();
145
- ctx.arc(0, 0, size, 0, Math.PI * 2);
146
- ctx.fill();
147
- ctx.restore();
148
  });
149
  });
150
  ctx.globalCompositeOperation = "source-over";
 
151
 
152
- // 4) comets with glow
153
  comets.forEach(c => {
154
- ctx.save();
155
- ctx.strokeStyle = "rgba(255,255,255,0.9)";
156
- ctx.lineWidth = 2;
157
- ctx.shadowColor = "white";
158
- ctx.shadowBlur = 8;
159
  ctx.beginPath();
160
  ctx.moveTo(c.x, c.y);
161
  ctx.lineTo(
@@ -163,18 +167,6 @@
163
  c.y - Math.sin(c.angle) * c.len
164
  );
165
  ctx.stroke();
166
- ctx.restore();
167
- });
168
-
169
- // 5) warp pulses
170
- pulses.forEach(p => {
171
- ctx.save();
172
- const grd = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r);
173
- grd.addColorStop(0, `rgba(255,255,255,${p.alpha})`);
174
- grd.addColorStop(1, "rgba(0,0,0,0)");
175
- ctx.fillStyle = grd;
176
- ctx.fillRect(0, 0, width, height);
177
- ctx.restore();
178
  });
179
  }
180
 
@@ -185,9 +177,10 @@
185
  requestAnimationFrame(loop);
186
  }
187
 
188
- // Initialize
189
  function init() {
190
  resize();
 
191
  initStars();
192
  window.addEventListener("resize", () => {
193
  resize();
 
1
+ // Optimized Starfield – Script Only
2
 
3
  (() => {
4
  const canvas = document.getElementById("starfield");
5
  const ctx = canvas.getContext("2d");
6
+ let width, height, bgCanvas, bgCtx;
7
+ let starSprites = [];
8
+ let layers = [];
 
9
  let comets = [];
10
+ let speedFactor = 1;
11
 
12
+ // Layer configuration: reduced counts & speeds tuned
13
+ const layerConfigs = [
14
+ { count: 300, speed: 0.5, size: 1.5 },
15
+ { count: 200, speed: 1.0, size: 2.5 },
16
+ { count: 100, speed: 2.0, size: 4.0 },
17
  ];
18
 
19
  // Utility
20
  const rand = (min, max) => min + Math.random() * (max - min);
21
 
22
+ // Resize & background cache
23
  function resize() {
 
24
  width = window.innerWidth;
25
  height = window.innerHeight;
26
+ canvas.width = width;
27
+ canvas.height = height;
28
+
29
+ // Cache radial background gradient once
30
+ bgCanvas = document.createElement("canvas");
31
+ bgCanvas.width = width;
32
+ bgCanvas.height = height;
33
+ bgCtx = bgCanvas.getContext("2d");
34
+ const grad = bgCtx.createRadialGradient(
35
+ width / 2, height / 2, 0,
36
+ width / 2, height / 2, width
37
+ );
38
+ grad.addColorStop(0, "rgba(30,30,40,0.3)");
39
+ grad.addColorStop(1, "black");
40
+ bgCtx.fillStyle = grad;
41
+ bgCtx.fillRect(0, 0, width, height);
42
+ }
43
+
44
+ // Pre-render star sprites of different radii
45
+ function createStarSprites() {
46
+ const radii = [1.2, 2.5, 4.0];
47
+ radii.forEach(r => {
48
+ const size = r * 4;
49
+ const off = document.createElement("canvas");
50
+ off.width = off.height = size;
51
+ const octx = off.getContext("2d");
52
+ octx.fillStyle = "#fff";
53
+ octx.shadowColor = "#fff";
54
+ octx.shadowBlur = r * 1.5;
55
+ octx.beginPath();
56
+ octx.arc(size / 2, size / 2, r, 0, Math.PI * 2);
57
+ octx.fill();
58
+ starSprites.push({ sprite: off, radius: r });
59
+ });
60
  }
61
 
62
  // Initialize star layers
63
  function initStars() {
64
+ layers = layerConfigs.map((cfg, idx) => {
65
  const stars = [];
66
  for (let i = 0; i < cfg.count; i++) {
67
  stars.push({
68
  x: rand(-width / 2, width / 2),
69
  y: rand(-height / 2, height / 2),
70
  z: rand(1, width),
71
+ a: rand(0.2, 1),
72
+ spriteIndex: idx, // reuse pre-rendered radii
73
  });
74
  }
75
  return { ...cfg, stars };
76
  });
77
  }
78
 
79
+ // Occasionally spawn a simple comet
80
  function maybeComet() {
81
+ if (Math.random() < 0.003) {
82
  comets.push({
83
  x: rand(0, width),
84
  y: rand(0, height * 0.2),
85
  len: 0,
86
+ maxLen: rand(80, 200),
87
  angle: Math.PI * 0.25 + rand(-0.2, 0.2),
88
+ speed: rand(8, 14),
89
  });
90
  }
91
  }
92
 
93
+ // Mouse speed control
 
 
 
 
 
 
 
 
 
 
 
94
  window.addEventListener("mousemove", e => {
95
+ speedFactor = 0.5 + (e.clientX / width) * 2.0;
96
  });
97
 
98
+ // Update positions & twinkle
99
  function update() {
100
+ layers.forEach(layer => {
101
+ const move = layer.speed * speedFactor;
102
  layer.stars.forEach(s => {
103
+ s.z -= move;
104
  if (s.z <= 0) {
105
  s.z = width;
106
  s.x = rand(-width / 2, width / 2);
107
  s.y = rand(-height / 2, height / 2);
108
+ s.a = rand(0.2, 1);
 
109
  }
110
+ // twinkle oscillation
111
+ s.a += Math.sin(Date.now() / 500 + s.z) * 0.002;
112
+ s.a = Math.max(0.2, Math.min(1, s.a));
113
  });
114
  });
115
 
 
120
  c.y += Math.sin(c.angle) * c.speed;
121
  });
122
 
 
 
 
 
 
 
123
  maybeComet();
124
  }
125
 
126
+ // Draw everything
127
  function draw() {
128
+ // 1) static background
129
+ ctx.drawImage(bgCanvas, 0, 0);
 
130
 
131
+ // 2) motion trails
132
+ ctx.fillStyle = "rgba(0,0,0,0.3)";
 
 
 
 
 
 
133
  ctx.fillRect(0, 0, width, height);
134
 
135
+ // 3) stars using cached sprites
136
+ layers.forEach((layer, li) => {
137
+ const { stars, size } = layer;
138
+ const { sprite, radius } = starSprites[li];
139
+ ctx.globalCompositeOperation = "lighter";
140
+ stars.forEach(s => {
141
  const k = (width / 2) / s.z;
142
  const x = s.x * k + width / 2;
143
  const y = s.y * k + height / 2;
144
  if (x < 0 || x > width || y < 0 || y > height) return;
145
+ const drawSize = (1 - s.z / width) * size * 2;
146
+ ctx.globalAlpha = s.a;
147
+ ctx.drawImage(
148
+ sprite,
149
+ x - drawSize,
150
+ y - drawSize,
151
+ drawSize * 2,
152
+ drawSize * 2
153
+ );
 
 
154
  });
155
  });
156
  ctx.globalCompositeOperation = "source-over";
157
+ ctx.globalAlpha = 1;
158
 
159
+ // 4) simple comets (no blur)
160
  comets.forEach(c => {
161
+ ctx.strokeStyle = "rgba(255,255,255,0.8)";
162
+ ctx.lineWidth = 1.5;
 
 
 
163
  ctx.beginPath();
164
  ctx.moveTo(c.x, c.y);
165
  ctx.lineTo(
 
167
  c.y - Math.sin(c.angle) * c.len
168
  );
169
  ctx.stroke();
 
 
 
 
 
 
 
 
 
 
 
 
170
  });
171
  }
172
 
 
177
  requestAnimationFrame(loop);
178
  }
179
 
180
+ // Initialize all
181
  function init() {
182
  resize();
183
+ createStarSprites();
184
  initStars();
185
  window.addEventListener("resize", () => {
186
  resize();