Aleksmorshen commited on
Commit
fd12e08
·
verified ·
1 Parent(s): 7e22858

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +372 -373
index.html CHANGED
@@ -1,133 +1,184 @@
1
  <!DOCTYPE html>
2
- <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
- <title>Arctic Mineral Water - Pure Refreshment</title>
7
  <style>
8
- /* Basic Reset */
9
  * {
10
  margin: 0;
11
  padding: 0;
12
  box-sizing: border-box;
13
  }
14
 
15
- html, body {
16
- overflow: hidden; /* Prevent default scrollbars */
17
- width: 100%;
18
- height: 100%;
 
19
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
20
- background-color: #051d30; /* Dark blue fallback */
21
  color: #fff;
 
 
 
 
22
  }
23
 
24
- /* Canvas Styling */
25
- #bg {
26
  position: fixed;
27
  top: 0;
28
  left: 0;
29
  width: 100%;
30
  height: 100%;
31
- z-index: -1; /* Behind other content */
32
- display: block; /* Prevents potential inline spacing issues */
 
 
 
 
33
  }
34
 
35
- /* Content Overlay Styling */
 
 
 
 
 
 
 
 
 
 
36
  .content-section {
37
- position: fixed;
38
- top: 50%;
39
- left: 50%;
40
- transform: translate(-50%, -50%);
41
- width: 80%;
42
- max-width: 600px;
43
- padding: 30px;
44
- background-color: rgba(15, 45, 70, 0.85); /* Semi-transparent dark blue */
45
- border-radius: 15px;
46
- border: 1px solid rgba(173, 216, 230, 0.5); /* Light blue border */
47
- box-shadow: 0 0 25px rgba(173, 216, 230, 0.3);
48
- opacity: 0;
49
- visibility: hidden;
50
- transition: opacity 0.8s ease-out, visibility 0.8s;
51
  text-align: center;
52
- z-index: 10;
53
- pointer-events: none; /* Allow clicking through initially */
 
 
 
 
54
  }
55
 
56
- .content-section.visible {
57
- opacity: 1;
58
- visibility: visible;
59
- pointer-events: auto; /* Allow interaction when visible */
60
  }
61
 
62
- .content-section h1 {
63
- font-size: 2.5em;
64
- margin-bottom: 15px;
65
- color: #e0faff; /* Very light blue */
66
- text-shadow: 0 0 10px #fff;
67
  }
68
 
69
- .content-section h2 {
70
- font-size: 1.8em;
71
- margin-bottom: 15px;
72
- color: #c0eaff;
73
- }
 
 
 
 
 
74
 
75
- .content-section p {
76
  font-size: 1.1em;
77
  line-height: 1.6;
78
- margin-bottom: 20px;
 
79
  }
80
 
81
- .content-section img.logo {
82
- max-width: 150px;
83
- margin-bottom: 20px;
 
 
84
  }
85
 
86
- /* Logo - Always Visible */
87
- .site-logo {
88
- position: fixed;
89
- top: 20px;
90
- left: 20px;
91
- width: 100px;
92
- height: auto;
93
- z-index: 100;
94
- filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.7));
 
 
 
 
95
  }
96
 
97
- /* Mobile Navigation Hint */
98
- .mobile-hint {
99
- position: fixed;
100
- bottom: 20px;
101
- left: 50%;
102
- transform: translateX(-50%);
103
- background-color: rgba(0, 0, 0, 0.6);
104
- color: #fff;
105
- padding: 8px 15px;
106
- border-radius: 20px;
107
- font-size: 0.9em;
108
- z-index: 50;
109
- display: none; /* Hidden by default, shown via JS for touch devices */
110
- animation: pulse 2s infinite;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
 
113
- @keyframes pulse {
114
- 0% { opacity: 1; }
115
- 50% { opacity: 0.7; }
116
- 100% { opacity: 1; }
 
 
 
 
 
 
117
  }
118
 
119
- /* Loading Indicator */
120
  #loader {
121
  position: fixed;
122
- top: 0;
123
- left: 0;
124
- width: 100%;
125
- height: 100%;
126
- background-color: #051d30;
127
  display: flex;
128
  justify-content: center;
129
  align-items: center;
130
- z-index: 200;
131
  color: #fff;
132
  font-size: 1.5em;
133
  }
@@ -136,321 +187,269 @@
136
  </head>
137
  <body>
138
 
139
- <!-- Always visible Logo -->
140
- <!-- Replace 'arctic_logo.png' with a Base64 encoded logo or a link if absolutely necessary -->
141
- <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImdSYSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNlMGZhZmYiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjYWRkOGU2Ii8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KICAKICA8IS0tIEJhY2tncm91bmQgQ2lyY2xlIC0tPgogIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjQ4IiBmaWxsPSJub25lIiBzdHJva2U9InVybCgjZ1JhKSIgc3Ryb2tlLXdpZHRoPSIzIiAvPgogIAogIDwhLS0gTW91bnRhaW4gU2hhcGVzIC0tPgogIDxwb2x5Z29uIHBvaW50cz0iMjUsNzUgNTAsMzAgNzUsNzUiIGZpbGw9InVybCgjZ1JhKSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjEiIC8+CiAgPHBvbHlnb24gcG9pbnRzPSIzNSw3NSA1NSw1MCA3MCw3NSIgZmlsbD0iIzE0MjgzOCIgb3BhY2l0eT0iMC44IiAvPgoKICA8IS0tIFdhdGVyIFJpcHBsZXMgLS0+CiAgPHBhdGggZD0iTTIwLDgwIEMzMCw3NSw0MCw4NSw1MCw4MCIgc3Ryb2tlPSIjYWRkOGU2IiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiIG9wYWNpdHk9IjAuNyIvPgogIDxwYXRoIGQ9Ik01MCw4MyBDNjAsNzgsNzAsODgsODAsODMiIHN0cm9rZT0iI2FkZDhlNiIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBvcGFjaXR5PSIwLjciLz4KCiAgPCEtLSBUZXh0ICJBIiAtLT4KICA8dGV4dCB4PSI1MCUiIHk9IjY1JSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9IlNlcmlmLCBTYW5zLXNlcmlmIiBmb250LXNpemU9IjM1IiBmaWxsPSIjZmZmIiBmb250LXdlaWdodD0iYm9sZCI+CiAgICBBCiAgPC90ZXh0Pgo8L3N2Zz4K" alt="Arctic Logo" class="site-logo">
142
-
143
- <!-- 3D Background Canvas -->
144
- <canvas id="bg"></canvas>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
- <!-- Loading Indicator -->
147
- <div id="loader">Loading Experience...</div>
148
-
149
- <!-- Content Sections (Initially Hidden) -->
150
- <div id="section-intro" class="content-section">
151
- <!-- You can add a logo image here too -->
152
- <!-- <img src="arctic_logo_white.png" alt="Arctic Logo" class="logo"> -->
153
- <h1>Arctic</h1>
154
- <p>Experience the Purest Water on Earth.</p>
155
- <p style="font-size: 0.9em; opacity: 0.8;">Scroll down or swipe up to explore.</p>
156
  </div>
157
 
158
- <div id="section-source" class="content-section">
159
- <h2>Our Source</h2>
160
- <p>Sourced directly from pristine Arctic glaciers, untouched by man. Filtered naturally through ancient ice, ensuring unparalleled purity and a crisp, refreshing taste.</p>
161
- </div>
162
-
163
- <div id="section-product" class="content-section">
164
- <h2>The Water</h2>
165
- <p>Perfectly balanced minerals provide a uniquely smooth taste. Available in Still and Sparkling. Choose Arctic for ultimate hydration and refreshment.</p>
166
- <!-- Add bottle images here if possible (Base64 or linked) -->
167
- </div>
168
-
169
- <div id="section-sustainability" class="content-section">
170
- <h2>Sustainability</h2>
171
- <p>Committed to preserving the Arctic. We use sustainable extraction methods and recyclable packaging to protect the environment that gives us our precious resource.</p>
172
- </div>
173
-
174
- <div id="section-contact" class="content-section">
175
- <h2>Contact Us</h2>
176
- <p>Learn more about Arctic or discuss partnership opportunities. Reach out to our team today.</p>
177
- <p>Email: [email protected]</p>
178
- </div>
179
-
180
- <!-- Mobile Navigation Hint -->
181
- <div class="mobile-hint">Swipe Up or Down to Navigate</div>
182
-
183
- <!-- Three.js Library (CDN) -->
184
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
185
-
186
- <!-- Main Application Logic -->
187
- <script>
188
- document.addEventListener('DOMContentLoaded', () => {
189
- const loader = document.getElementById('loader');
190
-
191
- // --- Configuration ---
192
- const scrollMultiplier = 0.005; // How much scroll affects camera movement
193
- const touchMultiplier = 0.008; // How much swipe affects camera movement
194
- const cameraStartZ = 5;
195
- const cameraEndZ = -45; // How "far" the user can scroll
196
- const lerpFactor = 0.08; // Smoothing factor for camera movement (lower = smoother)
197
- const fogNear = 1;
198
- const fogFar = 60;
199
- const fogColor = 0x051d30; // Match background
200
-
201
- const contentSections = [
202
- { id: 'section-intro', zStart: 5, zEnd: 0 },
203
- { id: 'section-source', zStart: -5, zEnd: -15 },
204
- { id: 'section-product', zStart: -20, zEnd: -30 },
205
- { id: 'section-sustainability', zStart: -35, zEnd: -42 },
206
- { id: 'section-contact', zStart: -44, zEnd: -50 } // A bit beyond camera end
207
- ];
208
-
209
- // --- Basic Scene Setup ---
210
- let scene, camera, renderer;
211
- let targetZ = cameraStartZ; // Target Z position for smooth animation
212
- let currentZ = cameraStartZ; // Actual current Z position
213
- let waterPlane, icebergs = [], particles;
214
-
215
- // --- Mobile Touch Handling ---
216
- let touchStartY = 0;
217
- let isTouching = false;
218
- const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
219
-
220
- function init() {
221
- // Scene
222
- scene = new THREE.Scene();
223
- scene.fog = new THREE.Fog(fogColor, fogNear, fogFar);
224
- scene.background = new THREE.Color(fogColor); // Set background color
225
-
226
- // Camera
227
- camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
228
- camera.position.set(0, 1, cameraStartZ); // Start slightly above water level
229
- camera.rotation.x = -0.1; // Slight downward look
230
-
231
- // Renderer
232
- const canvas = document.getElementById('bg');
233
- renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
234
- renderer.setSize(window.innerWidth, window.innerHeight);
235
- renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // Improve performance on high-res screens
236
-
237
- // --- Lighting ---
238
- const ambientLight = new THREE.AmbientLight(0xadeeff, 0.6); // Soft blue ambient light
239
- scene.add(ambientLight);
240
-
241
- const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); // Simulates sun/moon
242
- directionalLight.position.set(5, 10, 7);
243
- scene.add(directionalLight);
244
-
245
- // --- Create Scene Elements ---
246
- createWater();
247
- createIcebergs();
248
- createParticles(); // Add subtle particles
249
-
250
- // --- Event Listeners ---
251
- window.addEventListener('resize', onWindowResize);
252
- window.addEventListener('wheel', onScroll, { passive: false });
253
-
254
- if (isMobile) {
255
- document.querySelector('.mobile-hint').style.display = 'block';
256
- window.addEventListener('touchstart', onTouchStart, { passive: false });
257
- window.addEventListener('touchmove', onTouchMove, { passive: false });
258
- window.addEventListener('touchend', onTouchEnd);
259
- }
260
-
261
- // Hide loader and start animation
262
- loader.style.display = 'none';
263
- animate();
264
- }
265
-
266
- function createWater() {
267
- // Simple plane for water surface
268
- const waterGeometry = new THREE.PlaneGeometry(200, 200, 50, 50); // More segments for potential displacement later
269
- // Material that reacts to light, looks somewhat 'wet'
270
- const waterMaterial = new THREE.MeshStandardMaterial({
271
- color: 0x60a0d0, // Blueish color
272
- transparent: true,
273
- opacity: 0.85,
274
- roughness: 0.2, // Make it a bit shiny
275
- metalness: 0.1,
276
- side: THREE.DoubleSide,
277
- // wireframe: true // For debugging
278
- });
279
- waterPlane = new THREE.Mesh(waterGeometry, waterMaterial);
280
- waterPlane.rotation.x = -Math.PI / 2; // Lay flat
281
- waterPlane.position.y = -1; // Position slightly below camera origin
282
- scene.add(waterPlane);
283
  }
 
 
284
 
285
- function createIcebergs() {
286
- const icebergMaterial = new THREE.MeshStandardMaterial({
287
- color: 0xe0faff, // Very light blue/white
288
- roughness: 0.4,
289
- metalness: 0.0
290
- });
291
-
292
- const numIcebergs = 40;
293
- for (let i = 0; i < numIcebergs; i++) {
294
- const sizeX = Math.random() * 3 + 1;
295
- const sizeY = Math.random() * 5 + 2; // Taller
296
- const sizeZ = Math.random() * 3 + 1;
297
- const geometry = new THREE.BoxGeometry(sizeX, sizeY, sizeZ);
298
-
299
- // Simple deformation
300
- const positionAttribute = geometry.getAttribute('position');
301
- for (let j = 0; j < positionAttribute.count; j++) {
302
- const y = positionAttribute.getY(j);
303
- const modifier = (y + sizeY / 2) / sizeY; // Modify more towards the top
304
- positionAttribute.setX(j, positionAttribute.getX(j) + (Math.random() - 0.5) * 0.5 * modifier);
305
- positionAttribute.setZ(j, positionAttribute.getZ(j) + (Math.random() - 0.5) * 0.5 * modifier);
306
- if (y > 0) { // Taper top slightly
307
- positionAttribute.setX(j, positionAttribute.getX(j) * (1 - (y / sizeY)*0.4) );
308
- positionAttribute.setZ(j, positionAttribute.getZ(j) * (1 - (y / sizeY)*0.4) );
309
- }
310
- }
311
- geometry.computeVertexNormals(); // Recalculate normals after deformation
312
-
313
- const iceberg = new THREE.Mesh(geometry, icebergMaterial);
314
-
315
- const angle = Math.random() * Math.PI * 2;
316
- const distance = Math.random() * 30 + 10; // Distance from center path
317
- const x = Math.cos(angle) * distance;
318
- const z = Math.sin(angle) * distance - (i * (Math.abs(cameraEndZ - cameraStartZ)) / numIcebergs) - 15; // Spread along Z path
319
- const y = -1 + sizeY / 2 - Math.random() * 0.5; // Base slightly below water
320
-
321
- iceberg.position.set(x, y, z);
322
- iceberg.rotation.y = Math.random() * Math.PI * 2;
323
- iceberg.rotation.x = (Math.random() - 0.5) * 0.1;
324
- iceberg.rotation.z = (Math.random() - 0.5) * 0.1;
325
-
326
- scene.add(iceberg);
327
- icebergs.push(iceberg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
  }
329
- }
330
-
331
- function createParticles() {
332
- const particleCount = 5000;
333
- const positions = new Float32Array(particleCount * 3);
334
- const colors = new Float32Array(particleCount * 3);
335
- const color = new THREE.Color();
336
-
337
- for (let i = 0; i < particleCount; i++) {
338
- const i3 = i * 3;
339
- positions[i3] = (Math.random() - 0.5) * 80; // Spread wider
340
- positions[i3 + 1] = (Math.random() - 0.5) * 30 + 5; // Y range
341
- positions[i3 + 2] = (Math.random() - 0.5) * Math.abs(cameraEndZ - cameraStartZ) * 1.5 + (cameraEndZ/2); // Z range along path
342
-
343
- // Color based on depth (optional)
344
- // const depthMix = Math.max(0, Math.min(1, (positions[i3+2] - cameraEndZ) / (cameraStartZ - cameraEndZ)));
345
- color.setHSL(0.6, 0.9, Math.random() * 0.5 + 0.4); // Shades of blue/cyan
346
-
347
- colors[i3] = color.r;
348
- colors[i3 + 1] = color.g;
349
- colors[i3 + 2] = color.b;
350
  }
351
-
352
- const geometry = new THREE.BufferGeometry();
353
- geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
354
- geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
355
-
356
- const material = new THREE.PointsMaterial({
357
- size: 0.08,
358
- vertexColors: true,
359
- transparent: true,
360
- opacity: 0.7,
361
- blending: THREE.AdditiveBlending, // Looks nice for particles
362
- sizeAttenuation: true, // Smaller further away
363
- depthWrite: false // Prevent particles obscuring closer objects harshly
364
- });
365
-
366
- particles = new THREE.Points(geometry, material);
367
- scene.add(particles);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  }
369
 
370
- // --- Event Handlers ---
371
- function onWindowResize() {
372
- camera.aspect = window.innerWidth / window.innerHeight;
373
- camera.updateProjectionMatrix();
374
- renderer.setSize(window.innerWidth, window.innerHeight);
375
- renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
376
- }
377
 
378
- function onScroll(event) {
379
- event.preventDefault(); // Prevent default page scroll
380
- const scrollDelta = event.deltaY;
381
- targetZ -= scrollDelta * scrollMultiplier;
382
- // Clamp target Z within bounds
383
- targetZ = Math.max(cameraEndZ, Math.min(cameraStartZ, targetZ));
384
- }
385
 
386
- function onTouchStart(event) {
387
- // event.preventDefault(); // Only prevent if vertical scroll is intended
388
- if (event.touches.length === 1) {
389
- isTouching = true;
390
- touchStartY = event.touches[0].clientY;
391
- }
392
- }
393
-
394
- function onTouchMove(event) {
395
- if (!isTouching || event.touches.length !== 1) return;
396
- event.preventDefault(); // Prevent scrolling page while swiping on canvas
397
- const touchCurrentY = event.touches[0].clientY;
398
- const deltaY = touchCurrentY - touchStartY;
399
- targetZ += deltaY * touchMultiplier; // Inverted compared to scroll
400
- targetZ = Math.max(cameraEndZ, Math.min(cameraStartZ, targetZ));
401
- touchStartY = touchCurrentY; // Update start position for continuous swipe
402
- }
403
 
404
- function onTouchEnd() {
405
- isTouching = false;
406
- }
407
 
 
 
 
 
 
 
408
 
409
- // --- Content Visibility Logic ---
410
- function updateContentVisibility() {
411
- contentSections.forEach(section => {
412
- const element = document.getElementById(section.id);
413
- if (!element) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
 
415
- // Check if the camera's *current* Z is within the section's range
416
- if (currentZ < section.zStart && currentZ > section.zEnd) {
417
- element.classList.add('visible');
418
- } else {
419
- element.classList.remove('visible');
420
- }
421
- });
422
- }
423
 
 
 
424
 
425
- // --- Animation Loop ---
426
- function animate() {
427
- requestAnimationFrame(animate);
 
428
 
429
- const deltaTime = 0.016; // Assume ~60fps for simplicity, or use THREE.Clock
 
 
430
 
431
- // Smooth camera movement using lerp
432
- currentZ = THREE.MathUtils.lerp(currentZ, targetZ, lerpFactor);
433
- camera.position.z = currentZ;
 
434
 
435
- // Subtle water movement (optional, very basic)
436
- // waterPlane.material.displacementScale = 0.1; // Requires displacement map
437
- // waterPlane.material.needsUpdate = true; // If material props change
438
 
439
- // Subtle particle movement (optional)
440
- if (particles) {
441
- particles.rotation.y += 0.0005; // Slow rotation
442
- // You could also update individual particle positions here for flow effect (more complex)
443
- }
444
 
445
- // Update which content section is visible
446
- updateContentVisibility();
447
 
448
- renderer.render(scene, camera);
449
- }
 
 
 
 
 
450
 
451
- // --- Start ---
452
- init();
453
- });
454
  </script>
455
 
456
  </body>
 
1
  <!DOCTYPE html>
2
+ <html lang="ru">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>Arctic - Чистейшая Минеральная Вода</title>
7
  <style>
8
+ /* --- Базовые стили --- */
9
  * {
10
  margin: 0;
11
  padding: 0;
12
  box-sizing: border-box;
13
  }
14
 
15
+ html {
16
+ scroll-behavior: smooth; /* Плавный скролл по якорям (если нужны) */
17
+ }
18
+
19
+ body {
20
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 
21
  color: #fff;
22
+ background-color: #001f3f; /* Темно-синий фон на случай, если 3D не загрузится */
23
+ overflow-x: hidden; /* Запрещаем горизонтальный скролл */
24
+ /* Важно: Высота body должна быть больше viewport, чтобы был скролл */
25
+ /* Это достигается за счет высоты контентных секций */
26
  }
27
 
28
+ /* --- Контейнер для 3D сцены --- */
29
+ #canvas-container {
30
  position: fixed;
31
  top: 0;
32
  left: 0;
33
  width: 100%;
34
  height: 100%;
35
+ z-index: -1; /* Помещаем canvas позади контента */
36
+ overflow: hidden; /* Обрезаем все, что выходит за пределы */
37
+ }
38
+
39
+ canvas {
40
+ display: block; /* Убираем лишние отступы */
41
  }
42
 
43
+ /* --- Контейнер для контента --- */
44
+ #content-container {
45
+ position: relative; /* Чтобы z-index работал */
46
+ z-index: 1;
47
+ width: 100%;
48
+ max-width: 900px; /* Ограничиваем ширину контента на десктопах */
49
+ margin: 0 auto; /* Центрируем контент */
50
+ padding: 0 20px; /* Отступы по бокам */
51
+ }
52
+
53
+ /* --- Секции контента --- */
54
  .content-section {
55
+ min-height: 100vh; /* Каждая секция занимает минимум высоту экрана */
56
+ padding: 100px 20px 50px; /* Отступы внутри секции */
57
+ display: flex;
58
+ flex-direction: column;
59
+ justify-content: center;
60
+ align-items: center;
 
 
 
 
 
 
 
 
61
  text-align: center;
62
+ /* Полупрозрачный фон для лучшей читаемости */
63
+ background-color: rgba(10, 30, 60, 0.6);
64
+ margin-bottom: 5vh; /* Небольшой отступ между секциями */
65
+ border-radius: 15px;
66
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
67
+ transition: background-color 0.5s ease;
68
  }
69
 
70
+ .content-section:last-child {
71
+ margin-bottom: 0;
 
 
72
  }
73
 
74
+ /* --- Стилизация текста и элементов --- */
75
+ h1, h2, h3 {
76
+ margin-bottom: 20px;
77
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
 
78
  }
79
 
80
+ h1 {
81
+ font-size: 2.8em;
82
+ font-weight: bold;
83
+ color: #aee1f9; /* Светло-голубой */
84
+ }
85
+
86
+ h2 {
87
+ font-size: 2em;
88
+ color: #e0f7fa; /* Очень светло-голубой */
89
+ }
90
 
91
+ p {
92
  font-size: 1.1em;
93
  line-height: 1.6;
94
+ margin-bottom: 15px;
95
+ max-width: 600px; /* Ограничиваем ширину параграфов */
96
  }
97
 
98
+ .logo {
99
+ max-width: 200px;
100
+ margin-bottom: 30px;
101
+ /* filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.5)); */
102
+ /* Замените src на реальный логотип (лучше SVG или PNG с прозрачностью) */
103
  }
104
 
105
+ .cta-button {
106
+ display: inline-block;
107
+ padding: 12px 25px;
108
+ background-color: #00a8ff; /* Яркий голубой */
109
+ color: #fff;
110
+ border: none;
111
+ border-radius: 25px;
112
+ font-size: 1.1em;
113
+ text-decoration: none;
114
+ font-weight: bold;
115
+ cursor: pointer;
116
+ transition: background-color 0.3s ease, transform 0.2s ease;
117
+ box-shadow: 0 4px 8px rgba(0, 168, 255, 0.4);
118
  }
119
 
120
+ .cta-button:hover {
121
+ background-color: #007bb5; /* Темнее при наведении */
122
+ transform: translateY(-2px);
123
+ }
124
+
125
+ /* Адаптивность для меньших экранов */
126
+ @media (max-width: 768px) {
127
+ h1 { font-size: 2.2em; }
128
+ h2 { font-size: 1.8em; }
129
+ p { font-size: 1em; }
130
+ .content-section { padding: 80px 15px 40px; }
131
+ .logo { max-width: 150px; }
132
+ }
133
+
134
+ @media (max-width: 480px) {
135
+ h1 { font-size: 1.8em; }
136
+ h2 { font-size: 1.5em; }
137
+ p { font-size: 0.9em; }
138
+ .content-section { padding: 60px 10px 30px; min-height: 90vh; }
139
+ .logo { max-width: 120px; }
140
+ .cta-button { font-size: 1em; padding: 10px 20px; }
141
+ }
142
+
143
+ /* --- Стили для "продуктов" (просто пример) --- */
144
+ .product-gallery {
145
+ display: flex;
146
+ flex-wrap: wrap;
147
+ justify-content: center;
148
+ gap: 20px;
149
+ margin-top: 20px;
150
+ }
151
+
152
+ .product-item {
153
+ background-color: rgba(255, 255, 255, 0.1);
154
+ padding: 15px;
155
+ border-radius: 10px;
156
+ width: 150px; /* Фиксированная ширина для примера */
157
+ text-align: center;
158
  }
159
 
160
+ .product-item img {
161
+ max-width: 80px;
162
+ height: auto;
163
+ margin-bottom: 10px;
164
+ }
165
+
166
+ .product-item h3 {
167
+ font-size: 1em;
168
+ margin-bottom: 5px;
169
+ color: #fff;
170
  }
171
 
172
+ /* --- Простой индикатор загрузки --- */
173
  #loader {
174
  position: fixed;
175
+ top: 0; left: 0;
176
+ width: 100%; height: 100%;
177
+ background-color: #001f3f;
 
 
178
  display: flex;
179
  justify-content: center;
180
  align-items: center;
181
+ z-index: 1000;
182
  color: #fff;
183
  font-size: 1.5em;
184
  }
 
187
  </head>
188
  <body>
189
 
190
+ <!-- Индикатор загрузки -->
191
+ <div id="loader">Загрузка 3D сцены...</div>
192
+
193
+ <!-- Контейнер для Canvas -->
194
+ <div id="canvas-container"></div>
195
+
196
+ <!-- Основной контент сайта -->
197
+ <div id="content-container">
198
+
199
+ <!-- Секция 1: Главный экран -->
200
+ <section id="intro" class="content-section">
201
+ <!-- Замените на ваш логотип -->
202
+ <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNDUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2FlZTFmOSIgc3Ryb2tlLXdpZHRoPSI1Ii8+CiAgPHBhdGggZD0iTTMwIDQwIFE1MCAxNSA3MCA0MCIgc3Ryb2tlPSIjMDBlZWY4IiBzdHJva2Utd2lkdGg9IjUiIGZpbGw9Im5vbmUiLz4KICA8cGF0aCBkPSJNMzUgNjAgUTUwIDg1IDY1IDYwIiBzdHJva2U9IiMxN2RhZjIiIHN0cm9rZS13aWR0aD0iNCIgZmlsbD0ibm9uZSIvPgogIDx0ZXh0IHg9IjUwIiB5PSI3NSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkFjdGljPC90ZXh0Pgo8L3N2Zz4K" alt="Arctic Logo Placeholder" class="logo">
203
+ <h1>Arctic</h1>
204
+ <h2>Чистота северных глубин в каждой капле</h2>
205
+ <p>Откройте для себя вкус настоящей природной свежести. Вода "Arctic" добывается из артезианских источников, защищенных вечной мерзлотой.</p>
206
+ <a href="#about" class="cta-button">Узнать больше</a>
207
+ </section>
208
+
209
+ <!-- Секция 2: О нас -->
210
+ <section id="about" class="content-section">
211
+ <h2>Источник чистоты</h2>
212
+ <p>Наша вода проходит естественную фильтрацию через слои древних минеральных пород, обогащаясь полезными элементами и сохраняя свою первозданную структуру. Мы бережно доставляем ее вам, сохраняя все уникальные свойства.</p>
213
+ <p>Технологии XXI века и уважение к природе позволяют нам гарантировать высочайшее качество "Arctic".</p>
214
+ </section>
215
+
216
+ <!-- Секция 3: Продукция -->
217
+ <section id="products" class="content-section">
218
+ <h2>Наша линейка</h2>
219
+ <p>Выберите свой формат "Arctic" для любого случая.</p>
220
+ <div class="product-gallery">
221
+ <div class="product-item">
222
+ <!-- Замените на фото продукта -->
223
+ <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgODAgMTIwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IHg9IjEwIiB5PSIyMCIgd2lkdGg9IjYwIiBoZWlnaHQ9Ijk1IiByeD0iMTAiIGZpbGw9IiNhZWUxZjkiIG9wYWNpdHk9IjAuNyIvPgogIDxyZWN0IHg9IjIwIiB5PSI1IiB3aWR0aD0iNDAiIGhlaWdodD0iMjAiIHJ4PSI1IiBmaWxsPSIjZmZmIi8+CiAgPHJlY3QgeD0iMTUiIHk9IjI1IiB3aWR0aD0iNTAiIGhlaWdodD0iODAiIGZpbGw9IiNmZmYiIG9wYWNpdHk9IjAuMyIvPgo8L3N2Zz4K" alt="Бутылка 0.5л">
224
+ <h3>0.5л Негазированная</h3>
225
+ </div>
226
+ <div class="product-item">
227
+ <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgODAgMTIwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IHg9IjEwIiB5PSIyMCIgd2lkdGg9IjYwIiBoZWlnaHQ9Ijk1IiByeD0iMTAiIGZpbGw9IiMzYzkzYjgiIG9wYWNpdHk9IjAuNyIvPgogIDxyZWN0IHg9IjIwIiB5PSI1IiB3aWR0aD0iNDAiIGhlaWdodD0iMjAiIHJ4PSI1IiBmaWxsPSIjZmZmIi8+CiAgPHJlY3QgeD0iMTUiIHk9IjI1IiB3aWR0aD0iNTAiIGhlaWdodD0iODAiIGZpbGw9IiNmZmYiIG9wYWNpdHk9IjAuMyIvPgo8L3N2Zz4K" alt="Бутылка 1.5л">
228
+ <h3>1.5л Газированная</h3>
229
+ </div>
230
+ <div class="product-item">
231
+ <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgODAgMTIwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IHg9IjEwIiB5PSIyMCIgd2lkdGg9IjYwIiBoZWlnaHQ9Ijk1IiByeD0iMTAiIGZpbGw9IiNiM2U1ZmMiIG9wYWNpdHk9IjAuNyIvPgogIDxyZWN0IHg9IjIwIiB5PSI1IiB3aWR0aD0iNDAiIGhlaWdodD0iMjAiIHJ4PSI1IiBmaWxsPSIjZmZmIi8+CiAgPHJlY3QgeD0iMTUiIHk9IjI1IiB3aWR0aD0iNTAiIGhlaWdodD0iODAiIGZpbGw9IiNmZmYiIG9wYWNpdHk9IjAuMyIvPgo8L3N2Zz4K" alt="Бутылка 5л">
232
+ <h3>5л Негазированная (для дома и офиса)</h3>
233
+ </div>
234
+ </div>
235
+ </section>
236
+
237
+ <!-- Секция 4: Контакты -->
238
+ <section id="contact" class="content-section">
239
+ <h2>Связаться с нами</h2>
240
+ <p>Есть вопросы или предложения? Мы всегда рады общению.</p>
241
+ <p>Телефон: 8 (800) 123-45-67 (Звонок бесплатный)</p>
242
+ <p>Email: [email protected]</p>
243
+ <a href="mailto:[email protected]" class="cta-button">Написать нам</a>
244
+ </section>
245
 
 
 
 
 
 
 
 
 
 
 
246
  </div>
247
 
248
+ <!-- Подключение Three.js и аддонов -->
249
+ <script type="importmap">
250
+ {
251
+ "imports": {
252
+ "three": "https://unpkg.com/[email protected]/build/three.module.js",
253
+ "three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  }
255
+ }
256
+ </script>
257
 
258
+ <script type="module">
259
+ import * as THREE from 'three';
260
+ import { Water } from 'three/addons/objects/Water.js';
261
+ // OrbitControls можно добавить для отладки навигации, но для финальной версии скролла он не нужен
262
+ // import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
263
+
264
+ let scene, camera, renderer, water, clock;
265
+ let container;
266
+ let scrollY = 0;
267
+ let targetCameraZ = 15; // Начальная позиция камеры по Z
268
+ const cameraPathLength = 50; // Общая длина "пути" камеры по Z
269
+ const cameraBobbingAmplitude = 0.5; // Амплитуда покачивания камеры по Y
270
+ const cameraBobbingFrequency = 0.5; // Частота покачивания
271
+
272
+ const loaderElement = document.getElementById('loader');
273
+
274
+ function init() {
275
+ container = document.getElementById('canvas-container');
276
+ clock = new THREE.Clock();
277
+
278
+ // --- Сцена ---
279
+ scene = new THREE.Scene();
280
+ scene.fog = new THREE.FogExp2(0x0a1f30, 0.015); // Легкий туман для атмосферы
281
+
282
+ // --- Камера ---
283
+ camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
284
+ camera.position.set(0, 5, targetCameraZ); // Начальная позиция чуть выше воды
285
+ camera.lookAt(0, 2, 0); // Смотрим немного вниз к центру сцены
286
+
287
+ // --- Рендерер ---
288
+ renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false }); // alpha: false для непрозрачного фона
289
+ renderer.setSize(window.innerWidth, window.innerHeight);
290
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // Ограничиваем pixelRatio для производительности
291
+ renderer.toneMapping = THREE.ACESFilmicToneMapping; // Для более приятного вида
292
+ container.appendChild(renderer.domElement);
293
+
294
+ // --- Свет ---
295
+ const ambientLight = new THREE.AmbientLight(0xcccccc, 0.8); // Мягкий общий свет
296
+ scene.add(ambientLight);
297
+
298
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5); // Солнечный свет
299
+ directionalLight.position.set(-50, 50, 20);
300
+ // directionalLight.castShadow = true; // Тени могут сильно ударить по производительности, включать осторожно
301
+ scene.add(directionalLight);
302
+
303
+ // --- Вода ---
304
+ const waterGeometry = new THREE.PlaneGeometry(1000, 1000); // Большой плейн для воды
305
+
306
+ // Текстура для нормалей воды (создает эффект ряби)
307
+ // Используем текстуру из примеров three.js
308
+ const waterNormals = new THREE.TextureLoader().load(
309
+ 'https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/waternormals.jpg',
310
+ function ( texture ) {
311
+ texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
312
+ console.log("Water normals loaded successfully.");
313
+ // Убираем лоадер после загрузки текстуры
314
+ if (loaderElement) loaderElement.style.display = 'none';
315
+ // Начинаем анимацию только после загрузки
316
+ animate();
317
+ },
318
+ undefined, // onProgress callback (можно добавить)
319
+ function ( err ) {
320
+ console.error( 'An error happened loading the water texture:', err );
321
+ // Если текстура не загрузилась, все равно убираем лоадер и пытаемся рисовать
322
+ if (loaderElement) loaderElement.style.display = 'none';
323
+ animate(); // Пытаемся запустить анимацию даже без текстуры
324
  }
325
+ );
326
+
327
+
328
+ water = new Water(
329
+ waterGeometry,
330
+ {
331
+ textureWidth: 512,
332
+ textureHeight: 512,
333
+ waterNormals: waterNormals,
334
+ sunDirection: new THREE.Vector3(-50, 50, 20), // Направление света для отражений/бликов
335
+ sunColor: 0xffffff,
336
+ waterColor: 0x003e5f, // Цвет воды (темно-сине-зеленый)
337
+ distortionScale: 3.0, // Сила искажений ряби
338
+ fog: scene.fog !== undefined
 
 
 
 
 
 
 
339
  }
340
+ );
341
+
342
+ water.rotation.x = - Math.PI / 2; // Поворачиваем плейн, чтобы он был горизонтальным
343
+ water.position.y = 0; // Устанавливаем уровень воды
344
+ scene.add(water);
345
+
346
+ // --- Небо (простой вариант - куб с градиентом) ---
347
+ const skyGeometry = new THREE.SphereGeometry(500, 32, 16); // Большая сфера
348
+ const skyMaterial = new THREE.MeshBasicMaterial({
349
+ color: 0x87ceeb, // Цвет неба
350
+ side: THREE.BackSide, // Рендерим внутреннюю часть сферы
351
+ fog: false // Небо не подвержено туману
352
+ });
353
+ // Можно усложнить, сделав градиентный шейдер или загрузив CubeTexture
354
+ const sky = new THREE.Mesh(skyGeometry, skyMaterial);
355
+ sky.position.y = -10; // Слегка опускаем, чтобы горизонт был виден
356
+ scene.add(sky);
357
+
358
+ // --- (Опционально) Добавление простых объектов "айсбергов" ---
359
+ const icebergGeometry = new THREE.IcosahedronGeometry(5, 0); // Простая геометрия
360
+ const icebergMaterial = new THREE.MeshStandardMaterial({
361
+ color: 0xe0f7fa,
362
+ roughness: 0.7,
363
+ metalness: 0.1,
364
+ flatShading: true // "Граненый" вид
365
+ });
366
+
367
+ for (let i = 0; i < 5; i++) {
368
+ const iceberg = new THREE.Mesh(icebergGeometry, icebergMaterial);
369
+ iceberg.position.set(
370
+ (Math.random() - 0.5) * 150, // Разброс по X
371
+ Math.random() * 1 - 0.5, // Немного над/под водой
372
+ (Math.random() - 0.5) * 150 // Разброс по Z
373
+ );
374
+ iceberg.rotation.set(Math.random() * Math.PI, Math.random() * Math.PI, Math.random() * Math.PI);
375
+ iceberg.scale.setScalar(Math.random() * 2 + 1); // Разный размер
376
+ scene.add(iceberg);
377
  }
378
 
 
 
 
 
 
 
 
379
 
380
+ // --- Обработчики событий ---
381
+ window.addEventListener('resize', onWindowResize);
382
+ window.addEventListener('scroll', onScroll);
 
 
 
 
383
 
384
+ // Вызываем обработчик скролла один раз, чтобы установить начальную позицию камеры
385
+ onScroll();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
 
387
+ console.log("Three.js scene initialized.");
388
+ }
 
389
 
390
+ function onWindowResize() {
391
+ camera.aspect = window.innerWidth / window.innerHeight;
392
+ camera.updateProjectionMatrix();
393
+ renderer.setSize(window.innerWidth, window.innerHeight);
394
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
395
+ }
396
 
397
+ function onScroll() {
398
+ // Нормализуем скролл (от 0 до 1)
399
+ const scrollableHeight = document.documentElement.scrollHeight - window.innerHeight;
400
+ // Предотвращаем деление на ноль, если контент не прокручивается
401
+ const scrollProgress = scrollableHeight > 0 ? window.scrollY / scrollableHeight : 0;
402
+
403
+ // Обновляем целевую позицию камеры по Z
404
+ // Двигаемся от начальной точки `targetCameraZ` "вглубь" на `cameraPathLength`
405
+ targetCameraZ = 15 - (scrollProgress * cameraPathLength);
406
+
407
+ // Обновляем целевую позицию камеры по Y для эффекта покачивания
408
+ // Используем время (или скролл) для синусоиды
409
+ const time = clock.getElapsedTime(); // Можно использовать scrollProgress * N для зависимости от скролла
410
+ const bobbingY = Math.sin(time * cameraBobbingFrequency * Math.PI * 2) * cameraBobbingAmplitude;
411
+ const baseCameraY = 5; // Базовая высота камеры над водой
412
+ // targetCameraY = baseCameraY + bobbingY; // Пока без покачивания, чтобы сфокусироваться на Z
413
+ // camera.position.y = baseCameraY + bobbingY; // Обновляем Y с покачиванием
414
+
415
+ // Плавное перемещение камеры к целевым значениям (не в onScroll, а в animate)
416
+ }
417
 
418
+ function animate() {
419
+ requestAnimationFrame(animate);
 
 
 
 
 
 
420
 
421
+ const delta = clock.getDelta();
422
+ const time = clock.getElapsedTime();
423
 
424
+ // Анимация воды
425
+ if (water) {
426
+ water.material.uniforms['time'].value += delta * 0.5; // Скорость анимации воды
427
+ }
428
 
429
+ // Плавное (интерполированное) движение камеры к целевым значениям
430
+ const lerpFactor = 0.05; // Коэффициент плавности (меньше = плавнее, но медленнее)
431
+ camera.position.z += (targetCameraZ - camera.position.z) * lerpFactor;
432
 
433
+ // Добавляем покачивание на основе времени
434
+ const bobbingY = Math.sin(time * cameraBobbingFrequency * Math.PI * 2) * cameraBobbingAmplitude;
435
+ const targetCameraY = 5 + bobbingY; // Базовая высота + покачивание
436
+ camera.position.y += (targetCameraY - camera.position.y) * lerpFactor;
437
 
 
 
 
438
 
439
+ // Обновляем взгляд камеры (если нужно, чтобы она смотрела не прямо)
440
+ // camera.lookAt(0, 2, camera.position.z - 10); // Смотрим немного вперед по пути
 
 
 
441
 
442
+ renderer.render(scene, camera);
443
+ }
444
 
445
+ // Запускаем инициализацию
446
+ // Ждем загрузки DOM перед инициализацией Three.js
447
+ if (document.readyState === 'loading') {
448
+ document.addEventListener('DOMContentLoaded', init);
449
+ } else {
450
+ init(); // DOM уже загружен
451
+ }
452
 
 
 
 
453
  </script>
454
 
455
  </body>