victor HF staff commited on
Commit
cd788df
1 Parent(s): fde2381

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +334 -17
index.html CHANGED
@@ -1,19 +1,336 @@
1
- <!doctype html>
 
2
  <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+
2
+ <!DOCTYPE html>
3
  <html>
4
+ <head>
5
+ <title>Isometric SVG Grid with Sound and Responsive Layout</title>
6
+ <style>
7
+ html, body {
8
+ margin: 0;
9
+ padding: 0;
10
+ overflow: hidden;
11
+ height: 100%;
12
+ width: 100%;
13
+ background-color: #333;
14
+ }
15
+ svg {
16
+ display: block;
17
+ }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <svg id="svgGrid" width="100%" height="100%"></svg>
22
+ <script>
23
+ (function() {
24
+ const svgNS = "http://www.w3.org/2000/svg";
25
+ const svg = document.getElementById('svgGrid');
26
+ const gridSize = 20; // 20x20 grid
27
+ const tileSize = 40; // Base size for each tile
28
+
29
+ const tiles = [];
30
+ let lastClicked = null; // Keep track of the last clicked tile
31
+ let pathTiles = []; // Tiles in the current path
32
+
33
+ // Create AudioContext for playing sound
34
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
35
+
36
+ // Function to play click sound
37
+ function playClickSound() {
38
+ const oscillator = audioContext.createOscillator();
39
+ const gainNode = audioContext.createGain();
40
+
41
+ oscillator.connect(gainNode);
42
+ gainNode.connect(audioContext.destination);
43
+ oscillator.type = 'sine';
44
+ oscillator.frequency.setValueAtTime(440, audioContext.currentTime); // A4 note
45
+ gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
46
+ oscillator.start();
47
+ oscillator.stop(audioContext.currentTime + 0.1); // Play for 0.1 seconds
48
+ }
49
+
50
+ // Initialize the grid
51
+ initGrid();
52
+
53
+ // Add event listener for window resize
54
+ window.addEventListener('resize', onWindowResize);
55
+
56
+ function initGrid() {
57
+ // Remove any existing tiles from the SVG
58
+ while (svg.firstChild) {
59
+ svg.removeChild(svg.firstChild);
60
+ }
61
+
62
+ // Initialize tiles array
63
+ for (let y = 0; y < gridSize; y++) {
64
+ tiles[y] = tiles[y] || [];
65
+ for (let x = 0; x < gridSize; x++) {
66
+ const tileData = tiles[y][x] || {
67
+ x: x,
68
+ y: y,
69
+ element: null,
70
+ defaultColor: '#ccc',
71
+ isPath: false,
72
+ isClicked: false, // Indicates if the tile has been clicked
73
+ f: 0,
74
+ g: 0,
75
+ h: 0,
76
+ parent: null,
77
+ };
78
+
79
+ // Create the polygon element if it doesn't exist
80
+ if (!tileData.element) {
81
+ const polygon = document.createElementNS(svgNS, 'polygon');
82
+ polygon.setAttribute('fill', tileData.defaultColor);
83
+ polygon.setAttribute('stroke', '#999');
84
+ polygon.setAttribute('stroke-width', '1');
85
+ polygon.style.cursor = 'pointer';
86
+
87
+ // Randomly spawn obstacles (approximately 1 in 3 tiles)
88
+ if (Math.random() < 1 / 3) {
89
+ const randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
90
+ tileData.defaultColor = randomColor;
91
+ tileData.isClicked = true; // Mark tile as clicked (obstacle)
92
+ polygon.setAttribute('fill', randomColor);
93
+ }
94
+
95
+ // Add event listener for interactivity
96
+ polygon.addEventListener('click', function() {
97
+ // Play sound
98
+ playClickSound();
99
+
100
+ const randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
101
+ tileData.defaultColor = randomColor;
102
+ polygon.setAttribute('fill', randomColor);
103
+
104
+ // Highlight the path from the last clicked tile
105
+ if (lastClicked) {
106
+ clearPath(); // Clear previous path
107
+ resetTiles(); // Reset tile properties
108
+
109
+ // Mark the current tile as the end tile
110
+ const startTile = lastClicked;
111
+ const endTile = tileData;
112
+
113
+ // Temporarily set isClicked to false for pathfinding
114
+ const startWasClicked = startTile.isClicked;
115
+ const endWasClicked = endTile.isClicked;
116
+ startTile.isClicked = false;
117
+ endTile.isClicked = false;
118
+
119
+ const path = findPathAStar(startTile, endTile);
120
+ if (path.length > 0) {
121
+ animatePath(path);
122
+ } else {
123
+ alert('No path found!');
124
+ }
125
+
126
+ // After pathfinding, restore isClicked status
127
+ startTile.isClicked = startWasClicked;
128
+ endTile.isClicked = endWasClicked;
129
+ }
130
+
131
+ // Mark the tile as clicked after pathfinding
132
+ tileData.isClicked = true;
133
+ lastClicked = tileData; // Update last clicked tile
134
+ });
135
+
136
+ tileData.element = polygon;
137
+ svg.appendChild(polygon);
138
+ }
139
+
140
+ tiles[y][x] = tileData;
141
+ }
142
+ }
143
+
144
+ // Update positions of tiles
145
+ updateTilePositions();
146
+ }
147
+
148
+ function updateTilePositions() {
149
+ const width = window.innerWidth;
150
+ const height = window.innerHeight;
151
+
152
+ // Adjust tileSize to fit the screen
153
+ const scaleX = width / (gridSize * tileSize);
154
+ const scaleY = height / (gridSize * tileSize / 2);
155
+ const scale = Math.min(scaleX, scaleY);
156
+ const adjustedTileSize = tileSize * scale;
157
+
158
+ // Calculate grid dimensions
159
+ const gridWidth = gridSize * adjustedTileSize;
160
+ const gridHeight = gridSize * adjustedTileSize / 2;
161
+
162
+ // Calculate offsets to center the grid
163
+ const offsetX = (width - gridWidth) / 2;
164
+ const offsetY = (height - gridHeight) / 2;
165
+
166
+ // Origin point for the grid
167
+ const originX = offsetX + gridWidth / 2;
168
+ const originY = offsetY;
169
+
170
+ for (let y = 0; y < gridSize; y++) {
171
+ for (let x = 0; x < gridSize; x++) {
172
+ const tileData = tiles[y][x];
173
+
174
+ // Calculate the position of each tile
175
+ const isoX = (x - y) * (adjustedTileSize / 2);
176
+ const isoY = (x + y) * (adjustedTileSize / 4);
177
+
178
+ // Coordinates for the diamond shape
179
+ const points = [
180
+ { x: originX + isoX, y: originY + isoY },
181
+ { x: originX + isoX + adjustedTileSize / 2, y: originY + isoY + adjustedTileSize / 4 },
182
+ { x: originX + isoX, y: originY + isoY + adjustedTileSize / 2 },
183
+ { x: originX + isoX - adjustedTileSize / 2, y: originY + isoY + adjustedTileSize / 4 },
184
+ ];
185
+
186
+ tileData.element.setAttribute('points', points.map(p => `${p.x},${p.y}`).join(' '));
187
+ }
188
+ }
189
+ }
190
+
191
+ function onWindowResize() {
192
+ updateTilePositions();
193
+ }
194
+
195
+ // Function to reset tile properties before pathfinding
196
+ function resetTiles() {
197
+ for (let y = 0; y < gridSize; y++) {
198
+ for (let x = 0; x < gridSize; x++) {
199
+ const tile = tiles[y][x];
200
+ tile.f = 0;
201
+ tile.g = 0;
202
+ tile.h = 0;
203
+ tile.parent = null;
204
+ }
205
+ }
206
+ }
207
+
208
+ // Function to find the shortest path using A* algorithm
209
+ function findPathAStar(start, end) {
210
+ const openList = [];
211
+ const closedList = [];
212
+ openList.push(start);
213
+
214
+ while (openList.length > 0) {
215
+ // Find the tile with the lowest f value
216
+ let lowestIndex = 0;
217
+ for (let i = 0; i < openList.length; i++) {
218
+ if (openList[i].f < openList[lowestIndex].f) {
219
+ lowestIndex = i;
220
+ }
221
+ }
222
+ const currentTile = openList[lowestIndex];
223
+
224
+ // If we've reached the end tile, reconstruct the path
225
+ if (currentTile === end) {
226
+ const path = [];
227
+ let curr = currentTile;
228
+ path.push(curr); // Include the end tile
229
+ while (curr.parent) {
230
+ curr = curr.parent;
231
+ path.push(curr);
232
+ }
233
+ path.reverse();
234
+ return path;
235
+ }
236
+
237
+ // Move current tile from open to closed list
238
+ openList.splice(lowestIndex, 1);
239
+ closedList.push(currentTile);
240
+
241
+ // Get neighbors
242
+ const neighbors = getNeighbors(currentTile);
243
+
244
+ for (let neighbor of neighbors) {
245
+ if (closedList.includes(neighbor) || (neighbor.isClicked && neighbor !== end)) {
246
+ // Ignore the neighbor which is already evaluated or clicked (except the end tile)
247
+ continue;
248
+ }
249
+
250
+ const tentative_gScore = currentTile.g + 1;
251
+
252
+ if (!openList.includes(neighbor)) {
253
+ // Discover a new node
254
+ neighbor.g = tentative_gScore;
255
+ neighbor.h = heuristic(neighbor, end);
256
+ neighbor.f = neighbor.g + neighbor.h;
257
+ neighbor.parent = currentTile;
258
+ openList.push(neighbor);
259
+ } else if (tentative_gScore < neighbor.g) {
260
+ // This is a better path
261
+ neighbor.g = tentative_gScore;
262
+ neighbor.f = neighbor.g + neighbor.h;
263
+ neighbor.parent = currentTile;
264
+ }
265
+ }
266
+ }
267
+
268
+ // No path found
269
+ return [];
270
+ }
271
+
272
+ // Heuristic function (Manhattan distance)
273
+ function heuristic(a, b) {
274
+ return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
275
+ }
276
+
277
+ // Function to get neighbors of a tile
278
+ function getNeighbors(tile) {
279
+ const neighbors = [];
280
+ const dirs = [
281
+ { x: 0, y: -1 }, // Up
282
+ { x: 1, y: 0 }, // Right
283
+ { x: 0, y: 1 }, // Down
284
+ { x: -1, y: 0 }, // Left
285
+ // Uncomment below for diagonal movement
286
+ // { x: -1, y: -1 },
287
+ // { x: 1, y: -1 },
288
+ // { x: 1, y: 1 },
289
+ // { x: -1, y: 1 },
290
+ ];
291
+ for (let dir of dirs) {
292
+ const nx = tile.x + dir.x;
293
+ const ny = tile.y + dir.y;
294
+ if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize) {
295
+ neighbors.push(tiles[ny][nx]);
296
+ }
297
+ }
298
+ return neighbors;
299
+ }
300
+
301
+ // Function to animate the path
302
+ function animatePath(path) {
303
+ pathTiles = path;
304
+ let index = 0;
305
+
306
+ function highlightNextTile() {
307
+ if (index < path.length) {
308
+ const tile = path[index];
309
+ // Skip tiles that were clicked (they keep their color)
310
+ if (!tile.isClicked || tile === path[0] || tile === path[path.length - 1]) {
311
+ tile.element.setAttribute('fill', '#888'); // Highlight color
312
+ tile.isPath = true;
313
+ }
314
+ index++;
315
+ setTimeout(highlightNextTile, 100); // Adjust the delay as needed
316
+ }
317
+ }
318
+
319
+ highlightNextTile();
320
+ }
321
+
322
+ // Function to clear the previous path
323
+ function clearPath() {
324
+ pathTiles.forEach(tile => {
325
+ // Only reset tiles that are not the clicked ones
326
+ if (!tile.isClicked || tile === pathTiles[0] || tile === pathTiles[pathTiles.length - 1]) {
327
+ tile.element.setAttribute('fill', tile.defaultColor);
328
+ tile.isPath = false;
329
+ }
330
+ });
331
+ pathTiles = [];
332
+ }
333
+ })();
334
+ </script>
335
+ </body>
336
  </html>