Map is displayed and interactive
This commit is contained in:
parent
10a5db9d05
commit
99c22987e3
31
js/main.js
31
js/main.js
@ -9,11 +9,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
function switchMode(mode) {
|
function switchMode(mode) {
|
||||||
if (mode === 'create') {
|
if (mode === 'create') {
|
||||||
倉-> modeCreateBtn.classList.add('active');
|
modeCreateBtn.classList.add('active');
|
||||||
modeViewBtn.classList.remove('active');
|
modeViewBtn.classList.remove('active');
|
||||||
createPanel.classList.add('active-panel');
|
createPanel.classList.add('active-panel');
|
||||||
viewPanel.classList.remove('active-panel');
|
viewPanel.classList.remove('active-panel');
|
||||||
//ҧ Enable marker adding
|
// Enable marker adding
|
||||||
window.isCreatingJourney = true;
|
window.isCreatingJourney = true;
|
||||||
} else { // view mode
|
} else { // view mode
|
||||||
modeCreateBtn.classList.remove('active');
|
modeCreateBtn.classList.remove('active');
|
||||||
@ -40,6 +40,33 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
window.currentJourney.name = title;
|
window.currentJourney.name = title;
|
||||||
window.currentJourney.description = description;
|
window.currentJourney.description = description;
|
||||||
|
|
||||||
|
// Add the current journey to the journeys array if not already added
|
||||||
|
const existingJourneyIndex = window.journeys.findIndex(j => j.id === window.currentJourney.id);
|
||||||
|
if (existingJourneyIndex === -1) {
|
||||||
|
window.journeys.push({
|
||||||
|
id: window.currentJourney.id,
|
||||||
|
name: window.currentJourney.name,
|
||||||
|
description: window.currentJourney.description,
|
||||||
|
markers: window.currentJourney.markers.map(marker => ({
|
||||||
|
id: marker.id,
|
||||||
|
lngLat: marker.getLngLat(),
|
||||||
|
content: marker.content
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
window.journeys[existingJourneyIndex] = {
|
||||||
|
...window.journeys[existingJourneyIndex],
|
||||||
|
name: window.currentJourney.name,
|
||||||
|
description: window.currentJourney.description,
|
||||||
|
markers: window.currentJourney.markers.map(marker => ({
|
||||||
|
id: marker.id,
|
||||||
|
lngLat: marker.getLngLat(),
|
||||||
|
content: marker.content
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
window.saveJourneyToLocalStorage();
|
window.saveJourneyToLocalStorage();
|
||||||
|
|
||||||
// Show notification
|
// Show notification
|
||||||
|
|||||||
69
js/map.js
69
js/map.js
@ -11,21 +11,11 @@ let currentMarkerBeingEdited = null;
|
|||||||
let isCreatingJourney = true;
|
let isCreatingJourney = true;
|
||||||
|
|
||||||
function saveJourneyToLocalStorage() {
|
function saveJourneyToLocalStorage() {
|
||||||
journeys.push({
|
|
||||||
id: currentJourney.id,
|
|
||||||
name: currentJourney.name,
|
|
||||||
description: currentJourney.description,
|
|
||||||
markers: currentJourney.markers.map(marker => ({
|
|
||||||
id: marker.id,
|
|
||||||
lngLat: marker.getLngLat(),
|
|
||||||
content: marker.content
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
localStorage.setItem('journeys', JSON.stringify(journeys));
|
localStorage.setItem('journeys', JSON.stringify(journeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadJourneysFromLocalStorage() {
|
function loadJourneysFromLocalStorage() {
|
||||||
const stored = localStorage.getItem('journeyMapper_journeys');
|
const stored = localStorage.getItem('journeys');
|
||||||
if (stored) {
|
if (stored) {
|
||||||
journeys = JSON.parse(stored);
|
journeys = JSON.parse(stored);
|
||||||
}
|
}
|
||||||
@ -60,6 +50,8 @@ function createMarker(lngLat) {
|
|||||||
openMarkerEditor(marker);
|
openMarkerEditor(marker);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
currentJourney.markers.push(marker);
|
||||||
|
updateJourneyPath();
|
||||||
return marker;
|
return marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,10 +64,10 @@ function openMarkerEditor(marker) {
|
|||||||
document.getElementById('marker-coords').textContent =
|
document.getElementById('marker-coords').textContent =
|
||||||
`${marker.getLngLat().lng.toFixed(4)}, ${marker.getLngLat().lat.toFixed(4)}`;
|
`${marker.getLngLat().lng.toFixed(4)}, ${marker.getLngLat().lat.toFixed(4)}`;
|
||||||
|
|
||||||
// Update imagine review
|
// Update image review
|
||||||
const imagePreview = document.getElementById('image-preview');
|
const imagePreview = document.getElementById('image-preview');
|
||||||
imagePreview.innerHTML = '';
|
imagePreview.innerHTML = '';
|
||||||
学生学习 if (marker.content.images && marker.content.images.length > 0) {
|
if (marker.content.images && marker.content.images.length > 0) {
|
||||||
marker.content.images.forEach(img => {
|
marker.content.images.forEach(img => {
|
||||||
const imgEl = document.createElement('img');
|
const imgEl = document.createElement('img');
|
||||||
imgEl.src = img;
|
imgEl.src = img;
|
||||||
@ -91,6 +83,20 @@ function closeMarkerEditor() {
|
|||||||
currentMarkerBeingEdited = null;
|
currentMarkerBeingEdited = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to update the journey path
|
||||||
|
function updateJourneyPath() {
|
||||||
|
const coordinates = currentJourney.markers.map(marker => marker.getLngLat().toArray());
|
||||||
|
|
||||||
|
map.getSource('journey-path').setData({
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {},
|
||||||
|
geometry: {
|
||||||
|
type: 'LineString',
|
||||||
|
coordinates: coordinates
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
map = new maplibregl.Map({
|
map = new maplibregl.Map({
|
||||||
container: 'map',
|
container: 'map',
|
||||||
@ -163,22 +169,49 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
currentJourney.markers.splice(index, 1);
|
currentJourney.markers.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateJourneyPath(); // Update path after marker deletion
|
||||||
|
|
||||||
closeMarkerEditor();
|
closeMarkerEditor();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add marker on map click
|
// Add marker on map click
|
||||||
map.on('click', (e) => {
|
map.on('click', (e) => {
|
||||||
if (isCreatingJourney) {
|
if (isCreatingJourney) {
|
||||||
const marker = createMarker(e.lngLat);
|
createMarker(e.lngLat);
|
||||||
currentJourney.markers.push(marker);
|
|
||||||
updateJourneyPath();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save journey button
|
// Save journey button
|
||||||
document.getElementById('save-journey-btn').addEventListener('click', function() {
|
document.getElementById('save-journey').addEventListener('click', function() {
|
||||||
currentJourney.name = document.getElementById('journey-name').value;
|
currentJourney.name = document.getElementById('journey-title').value;
|
||||||
currentJourney.description = document.getElementById('journey-description').value;
|
currentJourney.description = document.getElementById('journey-description').value;
|
||||||
|
|
||||||
|
// Add the current journey to the journeys array if not already added
|
||||||
|
const existingJourneyIndex = journeys.findIndex(j => j.id === currentJourney.id);
|
||||||
|
if (existingJourneyIndex === -1) {
|
||||||
|
journeys.push({
|
||||||
|
id: currentJourney.id,
|
||||||
|
name: currentJourney.name,
|
||||||
|
description: currentJourney.description,
|
||||||
|
markers: currentJourney.markers.map(marker => ({
|
||||||
|
id: marker.id,
|
||||||
|
lngLat: marker.getLngLat(),
|
||||||
|
content: marker.content
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
journeys[existingJourneyIndex] = {
|
||||||
|
...journeys[existingJourneyIndex],
|
||||||
|
name: currentJourney.name,
|
||||||
|
description: currentJourney.description,
|
||||||
|
markers: currentJourney.markers.map(marker => ({
|
||||||
|
id: marker.id,
|
||||||
|
lngLat: marker.getLngLat(),
|
||||||
|
content: marker.content
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
saveJourneyToLocalStorage();
|
saveJourneyToLocalStorage();
|
||||||
alert('Journey saved!');
|
alert('Journey saved!');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,8 +5,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Journey Mapper - Interactive Map</title>
|
<title>Journey Mapper - Interactive Map</title>
|
||||||
|
|
||||||
<script src='https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.js'></script>
|
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.19.0/dist/maplibre-gl.css' />
|
||||||
<link href='https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css' rel='stylesheet' />
|
<script src='https://unpkg.com/maplibre-gl@5.19.0/dist/maplibre-gl.js'></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body { margin: 0; padding: 0; }
|
||||||
|
html, body, #map { height: 100%; }
|
||||||
|
</style>
|
||||||
|
|
||||||
<!-- Font Awesome Icons -->
|
<!-- Font Awesome Icons -->
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
@ -191,73 +196,52 @@
|
|||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="marker-title">Title</label>
|
<label for="marker-title"><i class="fas fa-heading"></i> Title</label>
|
||||||
<input type="text" id="marker-title" placeholder="Location name">
|
<input type="text" id="marker-title" placeholder="Marker title">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="marker-date">Date</label>
|
<label for="marker-date"><i class="fas fa-calendar"></i> Date</label>
|
||||||
<input type="date" id="marker-date">
|
<input type="date" id="marker-date">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="marker-text">Description</label>
|
<label for="marker-text"><i class="fas fa-align-left"></i> Description</label>
|
||||||
<textarea id="marker-text" placeholder="Share your experience at this location..."></textarea>
|
<textarea id="marker-text" placeholder="Marker description"></textarea>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label><i class="fas fa-images"></i> Images</label>
|
|
||||||
<div class="image-upload-area">
|
|
||||||
<div id="image-preview" class="image-preview">
|
|
||||||
<!-- Images will appear here -->
|
|
||||||
</div>
|
|
||||||
<div class="upload-actions">
|
|
||||||
<input type="file" id="image-upload" accept="image/*" multiple style="display: none;">
|
|
||||||
<button id="add-image" class="btn btn-small">
|
|
||||||
<i class="fas fa-plus"></i> Add Images
|
|
||||||
</button>
|
|
||||||
<button id="remove-images" class="btn btn-small btn-secondary">
|
|
||||||
<i class="fas fa-trash"></i> Clear
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="video-url"><i class="fas fa-video"></i> Video URL</label>
|
<label for="video-url"><i class="fas fa-video"></i> Video URL</label>
|
||||||
<input type="url" id="video-url" placeholder="YouTube or Vimeo URL">
|
<input type="text" id="video-url" placeholder="Video URL">
|
||||||
<small class="help-text">Paste a YouTube or Vimeo video link</small>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="coordinates">
|
<div class="form-group">
|
||||||
<p><strong>Coordinates:</strong> <span id="marker-coords">0, 0</span></p>
|
<label><i class="fas fa-images"></i> Images</label>
|
||||||
|
<div id="image-preview"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="marker-coords"><i class="fas fa-map-marker-alt"></i> Coordinates</label>
|
||||||
|
<input type="text" id="marker-coords" readonly>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button id="save-marker" class="btn btn-primary">
|
<button id="save-marker" class="btn btn-primary">Save Marker</button>
|
||||||
<i class="fas fa-save"></i> Save Marker
|
<button id="delete-marker" class="btn btn-danger">Delete Marker</button>
|
||||||
</button>
|
<button id="close-modal" class="btn btn-secondary">Cancel</button>
|
||||||
<button id="delete-marker" class="btn btn-danger">
|
|
||||||
<i class="fas fa-trash"></i> Delete Marker
|
|
||||||
</button>
|
|
||||||
<button id="cancel-marker" class="btn btn-secondary">
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Notification Toast (Hidden by default) -->
|
<!-- Notification Toast -->
|
||||||
<div id="toast" class="toast">
|
<div id="toast" class="toast">
|
||||||
<div class="toast-content">
|
<p id="toast-message"></p>
|
||||||
<span id="toast-message">Journey saved successfully!</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- JavaScript Files -->
|
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
<script src="js/map.js"></script>
|
<script src="js/map.js"></script>
|
||||||
<script src="js/journey-post.js"></script>
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user