-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
381 lines (335 loc) · 17.1 KB
/
index.html
File metadata and controls
381 lines (335 loc) · 17.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="keywords" content="Seismic station visualizer, ground motion visualization, station monitor, FDSN web service app">
<meta name="description" content="iOS app for interactive visualization of seismic station waveform data" />
<meta name="title" content="Wiggles: station monitor" />
<title>Wiggles</title>
<!-- responsiveness -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<!-- stylesheet -->
<link href="default.css" rel="stylesheet" type="text/css" />
<!-- iOS icon -->
<link rel="apple-touch-icon" href="./wiggles_icon.png"/>
<link rel="icon" sizes="152x152" href="./wiggles_icon.png"/>
<!-- ko-fi button style -->
<link href="https://fonts.googleapis.com/css?family=Quicksand:400,700" rel="stylesheet" type="text/css">
</head>
<body>
<header>
<div class="container">
<div class="imagetext">
<div class="logo">
<img src="figures/wiggles_icon.png" style="width: 80px; margin-right: 10px;">
</div>
<a href="/Wiggles/" class="logo">Wiggles</a>
</div>
</div>
<section id="title-section">
<div class="container">
<div class="imagetext">
<div style="width: 50%; padding: 50px 0 0 0;">
<h1>Earth's ground motion at seismic stations worldwide</h1>
</div>
<div class="title-image" style="max-width: 50%">
<img src="figures/wiggles_3d.png" style="width: 100%;">
</div>
</div>
</div>
</section>
</header>
<main role="main">
<div id="scrollContainer">
<canvas id="canvasBackground"></canvas>
</div>
<section id="description-section">
<div class="container">
<!--
<div style="height: 140px;"></div>
-->
<p style="text-align: center; color: var(--text-light)">
Available for free on the App Store.
</p>
<div class="app-store-button">
<!-- https://toolbox.marketingtools.apple.com/en-us/app-store/us -->
<a href="https://apps.apple.com/us/app/wiggles-station-monitor/id6752356469?itscg=30200&itsct=apps_box_badge&mttnsubad=6752356469" style="display: inline-block;">
<img src="https://toolbox.marketingtools.apple.com/api/v2/badges/download-on-the-app-store/black/en-us?releaseDate=1758499200" alt="Download on the App Store" style="width: 245px; height: 82px; vertical-align: middle; object-fit: contain;" />
</a>
</div>
</div>
</section>
<section id="features-section">
<div class="container">
<h2>Features</h2>
<p style="text-align: center; margin-bottom: 3rem; color: var(--text-light)">
These features will make you a ground motion explorer!
</p>
<div class="features-grid">
<div class="feature-item">
<h3>Near-realtime Data</h3>
<div class="imagetext">
<img id="feature-img-1"
src="figures/wiggles_1.png"
data-static="figures/wiggles_1.png"
data-gif="figures/wiggles_1.gif"
style="width: 200px; margin-right: 20px;">
<p>Access seismic data from global networks, updated every minute</p>
</div>
</div>
<div class="feature-item">
<h3>Global Stations</h3>
<div class="imagetext">
<img id="feature-img-2"
src="figures/wiggles_2.png"
data-static="figures/wiggles_2.png"
data-gif="figures/wiggles_2.gif"
style="width: 200px; margin-right: 20px;">
<p>Explore thousands of seismic stations worldwide with detailed metadata</p>
</div>
</div>
<div class="feature-item">
<h3>Interactive Charts</h3>
<div class="imagetext">
<img id="feature-img-3"
src="figures/wiggles_3.png"
data-static="figures/wiggles_3.png"
data-gif="figures/wiggles_3.gif"
style="width: 200px; margin-right: 20px;">
<p>Pinch, zoom (single-tap to select zoom window, double-tap to reset) and pan through high-resolution seismic waveforms</p>
</div>
</div>
<div class="feature-item">
<h3>Earthquake Tracking</h3>
<div class="imagetext">
<img id="feature-img-6"
src="figures/wiggles_6.png"
data-static="figures/wiggles_6.png"
data-gif="figures/wiggles_6.gif"
style="width: 200px; margin-right: 20px;">
<p>List current earthquake events with magnitude, depth and location data</p>
</div>
</div>
<div class="feature-item">
<h3>Custom Analysis</h3>
<div class="imagetext">
<img id="feature-img-4"
src="figures/wiggles_4.png"
data-static="figures/wiggles_4.png"
data-gif="figures/wiggles_4.gif"
style="width: 200px; margin-right: 20px;">
<p>Adjustable filters, spectrograms and analysis tools</p>
</div>
</div>
<div class="feature-item">
<h3>Educational Tool</h3>
<div class="imagetext">
<img id="feature-img-8"
src="figures/wiggles_8.png"
data-static="figures/wiggles_8.png"
data-gif="figures/wiggles_8.gif"
style="width: 200px; margin-right: 20px;">
<p>Learn seismology by exploring ground motion near you</p>
</div>
</div>
</div>
</div>
</section>
</main>
<footer>
<div class="container">
<hr>
<div class="legal-links">
<a href="/Wiggles/">Home</a>
<a href="/Wiggles/privacy">Privacy</a>
<a href="https://github.com/danielpeter/Wiggles">Contact
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" fill="grey" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</a>
</div>
<p style="margin: 1rem 0; color: var(--text-light); font-size: 0.9rem;">
© 2025 Wiggles.
</p>
</div>
</footer>
<!-- ko-fi floating button -->
<script src='https://storage.ko-fi.com/cdn/scripts/overlay-widget.js'></script>
<script>
kofiWidgetOverlay.draw('daniel_peter', {
'type': 'floating-chat',
'floating-chat.donateButton.text': 'Tip Me',
'floating-chat.donateButton.background-color': '#1323a1',
'floating-chat.donateButton.text-color': '#fff'
});
</script>
<!-- seismic trace animations -->
<script>
// Global variables (set during initialization)
let canvas, ctx;
// image scroll
let image = new Image();
let scrollX = 0;
const scrollSpeed = 0.5; // Pixels per frame
let isImageLoaded = false;
// traces
let traces = [];
const numberOfTraces = 5;
const lineWidth = 1.5;
const amplitude = 20; // Max displacement from center
const frequency = 0.025; // How "wiggly" the traces are
const speed = 1.5; // How fast they move
let time = 0;
// --- Configuration and Initialization ---
function initializeCanvas() {
canvas = document.getElementById('canvasBackground');
ctx = canvas.getContext('2d');
// Use the dimensions of the parent container for a responsive canvas
const container = document.getElementById('scrollContainer');
canvas.width = container.clientWidth;
canvas.height = container.clientHeight;
// Load the image
image.src = 'figures/station_book.png';
image.onload = () => {
isImageLoaded = true;
// Start the animation only once the image is ready
animate();
};
image.onerror = () => {
console.error("Failed to load image. Check the image URL.");
// Display an error message on the canvas itself?
ctx.fillStyle = '#CCC';
//ctx.font = '24px Inter';
//ctx.textAlign = 'center';
//ctx.fillText("Error loading image.", canvas.width / 2, canvas.height / 2);
};
// traces
initializeTraces();
}
function initializeTraces() {
traces = [];
for (let i = 0; i < numberOfTraces; i++) {
const factor = i / (numberOfTraces-1); // in range [0,1]
traces.push({
yOffset: 105, // Initial vertical position
phaseOffset: 0, // factor * Math.PI, // Math.random() * Math.PI * 2, // Random phase for independent wiggles
colorHue: (0.55 + factor * 0.2) * 360, // For a vivid color range
opacity: 0.4 + factor * 0.4,
amplitude: amplitude + factor * amplitude
});
}
}
// Handle resizing
function resizeCanvas() {
if (canvas) {
const container = document.getElementById('scrollContainer');
canvas.width = container.clientWidth;
canvas.height = container.clientHeight;
}
}
window.addEventListener('resize', resizeCanvas);
document.addEventListener('DOMContentLoaded', initializeCanvas);
// --- Animation Loop ---
function drawLoopingBackground() {
if (!isImageLoaded) return;
// Clear the canvas (optional, but good practice)
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Decrease the scroll position
scrollX -= scrollSpeed;
// scaled to fit the canvas height
const scaleFactor = canvas.height / image.height;
const scaledWidth = image.width * scaleFactor;
// Check for the loop condition
if (scrollX <= -scaledWidth) {
scrollX = 0;
}
// Draw the first image section
ctx.drawImage(
image,
0, 0, image.width, image.height, // Source rectangle
scrollX, 0, scaledWidth, canvas.height // Destination rectangle
);
// Draw the second image section immediately following the first
ctx.drawImage(
image,
0, 0, image.width, image.height, // Source rectangle
scrollX + scaledWidth, 0, scaledWidth, canvas.height // Destination rectangle
);
}
function drawTraces() {
// Use a transparent fill to create a fading trail effect
// Using a slightly darker transparent background to make vivid colors pop
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; // Darker transparent to allow colors to be more vivid
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < numberOfTraces; i++) {
const trace = traces[i];
ctx.beginPath();
// Starting point with a base wiggle
ctx.moveTo(0, trace.yOffset + Math.sin(trace.phaseOffset + time * frequency) * amplitude);
for (let x = 0; x < canvas.width; x++) {
// Combine base wiggle with another sine wave for more complexity
const y = trace.yOffset +
//Math.cos(x * 0.008 * Math.PI) * (
1.0 * (
Math.sin(x * 0.01 + trace.phaseOffset + time * frequency) * trace.amplitude * 0.8 +
Math.sin(x * 0.02 + time * frequency * 1.5) * trace.amplitude * 0.2 // second component for more "seismic" feel
);
ctx.lineTo(x, y);
}
// Fancy animated coloring based on hue
//ctx.strokeStyle = `hsla(${trace.colorHue}, 100%, 70%, 0.5)`; // More vivid saturation/lightness, slightly higher opacity
ctx.strokeStyle = `rgba(200, 200, 200, ${trace.opacity})`;
ctx.lineWidth = lineWidth;
ctx.stroke();
}
time += speed;
}
function animate() {
drawLoopingBackground();
drawTraces();
// Request the next frame for smooth animation
window.requestAnimationFrame(animate);
}
</script>
<script>
// --- for Image Hover Effects ---
document.addEventListener('DOMContentLoaded', () => {
// Select all images that have a 'data-gif' attribute
const featureImages = document.querySelectorAll('img[data-gif]');
featureImages.forEach(img => {
// Preload the GIF for a smoother transition
const gifPreload = new Image();
gifPreload.src = img.getAttribute('data-gif');
// Mouse Over: Change the src to the GIF
img.addEventListener('mouseover', function() {
// Get the GIF path from the data attribute
const gifSrc = this.getAttribute('data-gif');
if (gifSrc) {
this.src = gifSrc;
}
});
// Mouse Out: Change the src back to the static image
img.addEventListener('mouseout', function() {
// Get the static image path from the data attribute
const staticSrc = this.getAttribute('data-static');
if (staticSrc) {
this.src = staticSrc;
}
});
img.addEventListener('click', function(event) {
// Prevent the tap from navigating (if the image were wrapped in a link)
event.preventDefault();
const staticSrc = this.getAttribute('data-static');
const gifSrc = this.getAttribute('data-gif');
// Check the current source and toggle
if (this.src.includes(staticSrc)) {
// Currently static, switch to GIF
this.src = gifSrc;
} else {
// Currently GIF, switch back to static
this.src = staticSrc;
}
});
});
});
</script>
</body>
</html>