-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added timeline slider - Added more test markers - Heavy code cleanup/organization
- Loading branch information
1 parent
bfba420
commit d44a870
Showing
9 changed files
with
444 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"cSpell.words": [ | ||
"despawn" | ||
] | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,12 @@ | |
<title>Alaska History Webmap</title> | ||
|
||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.css" integrity="sha512-qveKnGrvOChbSzAdtSs8p69eoLegyh+1hwOMbmpCViIwj7rn4oJjdmMvWOuyQlTOZgTlZA0N2PXA7iA8/2TUYA==" crossorigin="anonymous" referrerpolicy="no-referrer" /> | ||
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css"> | ||
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css"> | ||
<link rel="stylesheet" href="styles.css"> | ||
|
||
<link rel="icon" type="image/x-icon" href="favicon.ico"> | ||
|
||
<!-- Prevent caching (to see GitHub Pages updates, might remove later) --> | ||
<meta http-equiv='cache-control' content='no-cache'> | ||
|
@@ -15,8 +20,13 @@ | |
</head> | ||
<body> | ||
<div id="map"></div> | ||
|
||
<div class="slider-styled" id="slider"></div> | ||
|
||
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.js" integrity="sha512-UOJe4paV6hYWBnS0c9GnIRH8PLm2nFK22uhfAvsTIqd3uwnWsVri1OPn5fJYdLtGY3wB11LGHJ4yPU1WFJeBYQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | ||
<script src="https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster.js"></script> | ||
<script src="mergeTooltips.js"></script> | ||
<script src="map.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,156 @@ | ||
// Initialize the map | ||
function initializeMap() { | ||
var map = L.map('map', { | ||
maxBounds: [[46.56, -189.14], // SW corner | ||
[73.15, -123.93]], // NE corner | ||
maxBoundsViscosity: 1.0, | ||
minZoom: calculateMinZoom() | ||
}).setView([64.793, -153.040], calculateMinZoom()); | ||
|
||
// OSM layer | ||
L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', { | ||
maxZoom: 8, | ||
attribution: '© <a href="https://www.opentopomap.org/">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank">CC-BY-SA</a>) | Add names + data source' | ||
}).addTo(map); | ||
|
||
// Listen for screen resize event | ||
window.addEventListener('resize', function(event) { | ||
map.setMinZoom(calculateMinZoom()); | ||
}); | ||
|
||
return map; | ||
} | ||
|
||
// Calculate minZoom based on screen width | ||
// Function to calculate minimum zoom based on screen width | ||
function calculateMinZoom() { | ||
var width = document.documentElement.clientWidth; | ||
return width < 768 ? 4 : 5; | ||
return document.documentElement.clientWidth < 768 ? 4 : 5; | ||
} | ||
|
||
// Load GeoJSON data and create markers | ||
function loadMarkers(map) { | ||
fetch('markerdata.geojson') | ||
.then(response => { | ||
if (!response.ok) { | ||
throw new Error('Failed to fetch marker data'); | ||
// Function to filter markers based on current slider years | ||
function filterMarkers() { | ||
geojsonLayer.eachLayer(layer => { | ||
const { startDate, endDate } = layer.feature.properties; | ||
const inRange = startDate <= currentEndYear && endDate >= currentStartYear; | ||
const fading = fadingMarkers.has(layer); | ||
const icon = layer._icon; | ||
|
||
if (inRange) { | ||
if (fading) { | ||
fadingMarkers.delete(layer); | ||
if (icon) icon.classList.remove('fade-out'); | ||
} | ||
if (icon && !icon.classList.contains('fade-in')) { | ||
icon.classList.add('fade-in'); | ||
setTimeout(() => icon.classList.add('show'), 10); | ||
} | ||
return response.json(); | ||
}) | ||
.then(data => { | ||
L.geoJSON(data, { | ||
pointToLayer: function (feature, latlng) { | ||
var marker = L.marker(latlng); | ||
var popupContent = ` | ||
<div> | ||
<h3>${feature.properties.description}</h3> | ||
<p>${feature.properties.startDate} - ${feature.properties.endDate}</p> | ||
</div>`; | ||
|
||
var maxWidth = feature.properties.hasImage ? "auto" : feature.properties.maxWidth || 200; | ||
if (feature.properties.hasImage) { | ||
popupContent += `<img src="${feature.properties.imageUrl}" alt="Marker Image" style="max-width: 200px;">`; | ||
} | ||
|
||
marker.bindPopup(popupContent, { maxWidth: maxWidth }); | ||
|
||
// Add click event listener to marker, pan to on click | ||
marker.on('click', function() { | ||
map.panTo(marker.getLatLng()); | ||
}); | ||
|
||
return marker; | ||
map.addLayer(layer); | ||
} else { | ||
if (!fading) { | ||
fadingMarkers.add(layer); | ||
if (icon) { | ||
icon.classList.add('fade-out'); | ||
setTimeout(() => { | ||
if (fadingMarkers.has(layer)) { | ||
map.removeLayer(layer); | ||
fadingMarkers.delete(layer); | ||
} | ||
}, 500); | ||
} | ||
}).addTo(map); | ||
}) | ||
.catch(error => { | ||
console.error('Error loading marker data:', error); | ||
}); | ||
} | ||
if (icon && icon.classList.contains('fade-in')) { | ||
icon.classList.remove('fade-in', 'show'); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
// Function to initialize the slider | ||
function initializeSlider() { | ||
const slider = document.getElementById('slider'); | ||
|
||
// Destroy existing slider instance | ||
if (slider.noUiSlider) slider.noUiSlider.destroy(); | ||
|
||
noUiSlider.create(slider, { | ||
start: [currentStartYear, currentEndYear], | ||
connect: true, | ||
tooltips: [true, true], | ||
format: { to: function (value) { return Math.round(value); }, | ||
from: function (value) { return value; } | ||
}, | ||
range: { 'min': 1750, 'max': 2024 } | ||
}); | ||
|
||
mergeTooltips(slider, Math.floor(9438/window.innerWidth), ' - '); | ||
|
||
// Listen for slider changes | ||
slider.noUiSlider.on('update', function(values) { | ||
currentStartYear = parseInt(values[0]); | ||
currentEndYear = parseInt(values[1]); | ||
filterMarkers(); | ||
}); | ||
} | ||
|
||
document.addEventListener('DOMContentLoaded', function() { | ||
var map = initializeMap(); | ||
loadMarkers(map); | ||
// Map initialization | ||
const map = L.map('map', { | ||
maxBounds: [[46.56, -189.14],[73.15, -123.93]], | ||
maxBoundsViscosity: 0.5, | ||
minZoom: calculateMinZoom(), | ||
maxZoom: 8 | ||
}).setView([64.793, -153.040], calculateMinZoom()); | ||
|
||
// Add tile layer to map | ||
L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', { | ||
attribution: '© <a href="https://www.opentopomap.org/">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank">CC-BY-SA</a>)' | ||
}).addTo(map); | ||
|
||
// Set slider handle start and end years | ||
let [currentStartYear, currentEndYear] = [1750, 2024]; | ||
|
||
// Set to keep track of markers currently fading out | ||
let fadingMarkers = new Set(); | ||
|
||
// Load GeoJSON data | ||
let geojsonLayer = L.geoJSON(null, { | ||
onEachFeature: function(feature, layer) { | ||
const properties = feature.properties; | ||
const title = properties.startDate + " - " + properties.endDate; | ||
|
||
let popupContent = "<h3>" + title + "</h3>"; | ||
popupContent += properties.description; | ||
var maxWidth = feature.properties.hasImage ? "auto" : feature.properties.maxWidth || 200; | ||
if (properties.hasImage) { | ||
popupContent += "<img src='" + properties.imageUrl + "' alt='Marker Image' style='max-width: 200px;'>"; | ||
} | ||
|
||
// Bind popup to marker layer | ||
layer.bindPopup(popupContent, { maxWidth : maxWidth }); | ||
|
||
// Create a custom icon for the marker with no shadow | ||
var customIcon = L.icon({ | ||
iconUrl: 'data/icons/pin.png', // URL to the marker icon image | ||
iconSize: [30, 30], // Size of the icon image | ||
iconAnchor: [10, 30], // Anchor point of the icon image | ||
popupAnchor: [6, -30], // Popup anchor relative to the icon | ||
shadowUrl: '', // No shadow URL | ||
shadowSize: [0, 0], // No shadow size | ||
shadowAnchor: [0, 0] // No shadow anchor | ||
}); | ||
|
||
// Set the custom icon for the marker | ||
layer.setIcon(customIcon); | ||
} | ||
}).addTo(map); | ||
|
||
// Fetch GeoJSON data and add it to the map | ||
fetch('markerdata.geojson') | ||
.then(response => response.json()) | ||
.then(data => { | ||
geojsonLayer.addData(data); | ||
filterMarkers(); // Filter markers initially | ||
}); | ||
|
||
// Initialize slider | ||
initializeSlider(); | ||
|
||
// Listen for window resize event : reinitialize slider and calculate minZoom | ||
window.addEventListener('resize', function() { | ||
map.setMinZoom(calculateMinZoom()); | ||
initializeSlider(); | ||
}); | ||
|
||
/* | ||
TO DO: | ||
- Markers with uncertain location load a geographical location blob/circle | ||
- Markers cluster when close together (check case of clustered markers changing number when moving range) | ||
- Marker popup should have optional image, bold date, description under | ||
- Marker popup should have two tabs, one for source or more info? | ||
- About button top right, question mark icon that opens a new window (story board?) you can scroll through and exit out of | ||
- GitHub link | ||
- License | ||
- Attribution | ||
- Favicon | ||
- Marker image | ||
- noUISlider | ||
- noUiSlider merge function | ||
- General info + authors + data source | ||
- Custom domain | ||
- GitHub page organization | ||
*/ |
Oops, something went wrong.