Skip to content

Commit 2f96199

Browse files
authored
Add files via upload
Signed-off-by: Azure <[email protected]>
1 parent 98c8f60 commit 2f96199

File tree

3 files changed

+217
-1
lines changed

3 files changed

+217
-1
lines changed

index.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<nav class="top-nav">
1717
<div class="nav-content">
1818
<div class="nav-title">
19-
<span>NAKSHATRA</span>
19+
<span>Revels MIT Map</span>
2020
</div>
2121
<div class="nav-controls">
2222
<button id="toggleLegend" class="nav-button">
@@ -147,6 +147,10 @@ <h3>Map Legend</h3>
147147
</div>
148148
</div>
149149
</div>
150+
<!-- Events Popup Sidebar -->
151+
<div id="eventsPopup" class="location-sidebar">
152+
<div id="eventsContent"></div>
153+
</div>
150154

151155
<!-- Location Info Sidebar -->
152156

script.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,17 @@ const map = new ol.Map({
183183
]
184184
});
185185

186+
// Load events data
187+
let eventsData = [];
188+
fetch('data/revels_events.json')
189+
.then(response => response.json())
190+
.then(data => {
191+
if (data.ok) {
192+
eventsData = data.data;
193+
}
194+
})
195+
.catch(error => console.error('Error loading events:', error));
196+
186197
// Vector Sources Array and Layers Object
187198
const vectorSources = [];
188199
const layers = {};
@@ -241,6 +252,85 @@ Object.entries(layerConfigs).forEach(([id, config]) => {
241252
addGeoJSONLayer(config.url, config.style, id);
242253
});
243254

255+
// Add location pointer for "MIT Ground"
256+
const sportsSource = layers.sports.getSource();
257+
sportsSource.once('change', function() {
258+
if (sportsSource.getState() === 'ready') {
259+
const mitGround = sportsSource.getFeatures().find(feature =>
260+
feature.get('Sports') === 'MIT Ground'
261+
);
262+
if (mitGround) {
263+
const geometry = mitGround.getGeometry();
264+
const centroid = ol.extent.getCenter(geometry.getExtent());
265+
266+
const pointer = new ol.Feature({
267+
geometry: new ol.geom.Point(centroid),
268+
});
269+
pointer.setStyle(new ol.style.Style({
270+
image: new ol.style.Icon({
271+
src: 'https://cdn-icons-png.flaticon.com/512/684/684908.png', // Free pin icon
272+
scale: 0.05, // Adjust size as needed
273+
anchor: [0.5, 1], // Bottom-center of the pin
274+
}),
275+
}));
276+
277+
pointerSource.addFeature(pointer);
278+
}
279+
}
280+
});
281+
// Add pointers for additional event locations
282+
const additionalLocations = [
283+
{ layerId: 'shops', property: 'Shops', value: 'Student Plaza' },
284+
{ layerId: 'academic', property: 'Name', value: 'AB1' },
285+
{ layerId: 'academic', property: 'Name', value: 'AB2' },
286+
{ layerId: 'academic', property: 'Name', value: 'AB3' },
287+
{ layerId: 'academic', property: 'Name', value: 'AB5' },
288+
{ layerId: 'academic', property: 'Name', value: 'Library' },
289+
{ layerId: 'academic', property: 'Name', value: 'KEF R&D Centre' },
290+
];
291+
292+
additionalLocations.forEach(location => {
293+
const source = layers[location.layerId].getSource();
294+
source.once('change', function() {
295+
if (source.getState() === 'ready') {
296+
const feature = source.getFeatures().find(f =>
297+
f.get(location.property) === location.value
298+
);
299+
if (feature) {
300+
const geometry = feature.getGeometry();
301+
const centroid = ol.extent.getCenter(geometry.getExtent());
302+
const pointer = new ol.Feature({
303+
geometry: new ol.geom.Point(centroid),
304+
name: location.value, // Store for reference
305+
});
306+
pointer.setStyle(new ol.style.Style({
307+
image: new ol.style.Icon({
308+
src: 'https://cdn-icons-png.flaticon.com/512/684/684908.png',
309+
scale: 0.05,
310+
anchor: [0.5, 1],
311+
}),
312+
}));
313+
pointerSource.addFeature(pointer);
314+
}
315+
}
316+
});
317+
});
318+
319+
// Click handler for pointers
320+
map.on('click', function(event) {
321+
const feature = map.forEachFeatureAtPixel(event.pixel, function(feat, layer) {
322+
return layer === pointerLayer ? feat : null; // Only detect pointerLayer features
323+
});
324+
325+
if (feature) {
326+
const locationName = feature.get('name');
327+
showEventsPopup(locationName);
328+
} else {
329+
const popup = document.getElementById('eventsPopup');
330+
popup.classList.remove('active');
331+
}
332+
});
333+
244334
// User Position Tracking
245335
let userPositionSource = new ol.source.Vector();
246336
let userPositionLayer = new ol.layer.Vector({
@@ -263,6 +353,14 @@ let userPositionLayer = new ol.layer.Vector({
263353
// Add user position layer to map
264354
map.addLayer(userPositionLayer);
265355

356+
// Pointer layer for event tracking
357+
const pointerSource = new ol.source.Vector();
358+
const pointerLayer = new ol.layer.Vector({
359+
source: pointerSource,
360+
zIndex: 1001 // Above other layers, including user position
361+
});
362+
map.addLayer(pointerLayer);
363+
266364
// User position tracking feature
267365
let userPositionFeature = new ol.Feature();
268366
userPositionSource.addFeature(userPositionFeature);
@@ -667,3 +765,56 @@ setInterval(updateTime, 1000);
667765
// Initialize Map
668766
fitMapToFeatures();
669767
updateTime();
768+
769+
// Show events popup
770+
function showEventsPopup(locationName) {
771+
const relevantEvents = eventsData.filter(event =>
772+
(event.Name && event.Name === locationName) ||
773+
(event.Shops && event.Shops === locationName) ||
774+
(event.Sports && event.Sports === locationName)
775+
);
776+
777+
const popup = document.getElementById('eventsPopup');
778+
const content = document.getElementById('eventsContent');
779+
780+
// Clear previous content
781+
content.innerHTML = '';
782+
783+
// Build events list
784+
content.innerHTML = `
785+
<h2>Events at ${locationName}</h2>
786+
<ul class="events-list">
787+
${relevantEvents.map(event => `
788+
<li class="event-item" onclick="showEventDetails('${event.event_name.replace(/'/g, "\\'")}', '${locationName.replace(/'/g, "\\'")}')">
789+
<strong>${event.event_name}</strong><br>
790+
${new Date(event.event_date).toLocaleDateString()} ${event.event_time}
791+
</li>
792+
`).join('')}
793+
</ul>
794+
`;
795+
796+
popup.classList.add('active');
797+
}
798+
799+
// Show event details
800+
function showEventDetails(eventName, locationName) {
801+
const event = eventsData.find(e =>
802+
e.event_name === eventName && (
803+
(e.Name && e.Name === locationName) ||
804+
(e.Shops && e.Shops === locationName) ||
805+
(e.Sports && e.Sports === locationName)
806+
)
807+
);
808+
809+
const content = document.getElementById('eventsContent');
810+
content.innerHTML = `
811+
<h2>${event.event_name}</h2>
812+
<p><strong>Type:</strong> ${event.event_type}</p>
813+
<p><strong>Description:</strong> ${event.event_desc.replace(/\n/g, '<br>')}</p>
814+
<p><strong>Date:</strong> ${new Date(event.event_date).toLocaleDateString()}</p>
815+
<p><strong>Time:</strong> ${event.event_time}</p>
816+
<p><strong>Venue:</strong> ${event.venue_name}</p>
817+
<p><strong>Team Type:</strong> ${event.team_type}</p>
818+
<button onclick="showEventsPopup('${locationName.replace(/'/g, "\\'")}')">Back to Events</button>
819+
`;
820+
}

styles.css

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,3 +475,64 @@ html, body {
475475
.control-button:active {
476476
transform: scale(0.95);
477477
}
478+
.pointer-icon {
479+
transition: transform 0.2s;
480+
}
481+
482+
.pointer-icon:hover {
483+
transform: scale(1.1);
484+
}
485+
.location-sidebar {
486+
position: absolute;
487+
top: 0;
488+
right: -300px;
489+
width: 300px;
490+
height: 100%;
491+
background: rgba(255, 255, 255, 0.95);
492+
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
493+
transition: right 0.3s ease;
494+
z-index: 1000;
495+
overflow-y: auto;
496+
padding: 20px;
497+
box-sizing: border-box;
498+
}
499+
500+
.location-sidebar.active {
501+
right: 0;
502+
}
503+
504+
.events-list {
505+
list-style: none;
506+
padding: 0;
507+
margin: 0;
508+
}
509+
510+
.event-item {
511+
padding: 10px;
512+
border-bottom: 1px solid #ddd;
513+
cursor: pointer;
514+
transition: background 0.2s;
515+
}
516+
517+
.event-item:hover {
518+
background: #f5f5f5;
519+
}
520+
521+
.event-item strong {
522+
font-size: 1.1em;
523+
}
524+
525+
button {
526+
margin-top: 10px;
527+
padding: 8px 16px;
528+
background: var(--green);
529+
color: #fff;
530+
border: none;
531+
border-radius: 4px;
532+
cursor: pointer;
533+
transition: background 0.2s;
534+
}
535+
536+
button:hover {
537+
background: #7cc33a;
538+
}

0 commit comments

Comments
 (0)