feat: Add geocoding functionality and implement pan/zoom for the family tree view.
This commit is contained in:
parent
216385b638
commit
bf5a0876b6
3 changed files with 119 additions and 1 deletions
|
|
@ -116,7 +116,10 @@
|
|||
|
||||
<div class="form-group">
|
||||
<label>Sted</label>
|
||||
<input type="text" id="location" placeholder="F.eks. Kristiansand">
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<input type="text" id="location" placeholder="F.eks. Kristiansand">
|
||||
<button type="button" id="geocodeBtn" class="icon-btn" title="Finn koordinater">📍</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
|
|
|
|||
94
script.js
94
script.js
|
|
@ -196,6 +196,25 @@ memberForm.addEventListener('submit', (e) => {
|
|||
}
|
||||
});
|
||||
|
||||
// Geocoding
|
||||
document.getElementById('geocodeBtn').addEventListener('click', () => {
|
||||
const location = document.getElementById('location').value;
|
||||
if (!location) return;
|
||||
|
||||
const geocoder = new google.maps.Geocoder();
|
||||
geocoder.geocode({ 'address': location }, (results, status) => {
|
||||
if (status === 'OK') {
|
||||
const lat = results[0].geometry.location.lat();
|
||||
const lng = results[0].geometry.location.lng();
|
||||
|
||||
document.getElementById('lat').value = lat.toFixed(6);
|
||||
document.getElementById('lng').value = lng.toFixed(6);
|
||||
} else {
|
||||
alert('Kunne ikke finne koordinater for dette stedet: ' + status);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// --- Feature: Family Tree ---
|
||||
|
||||
function renderTree() {
|
||||
|
|
@ -490,3 +509,78 @@ function renderHistory() {
|
|||
list.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
// --- Feature: Family Tree Navigation (Pan/Zoom) ---
|
||||
|
||||
let treeState = {
|
||||
scale: 1,
|
||||
panning: false,
|
||||
pointX: 0,
|
||||
pointY: 0,
|
||||
startX: 0,
|
||||
startY: 0
|
||||
};
|
||||
|
||||
function setupPanZoom() {
|
||||
const treeTab = document.getElementById('tree-tab');
|
||||
const treeContainer = document.getElementById('tree-container');
|
||||
|
||||
// Zoom (Wheel)
|
||||
treeTab.addEventListener('wheel', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const xs = (e.clientX - treeState.pointX) / treeState.scale;
|
||||
const ys = (e.clientY - treeState.pointY) / treeState.scale;
|
||||
|
||||
const delta = -e.deltaY;
|
||||
(delta > 0) ? (treeState.scale *= 1.1) : (treeState.scale /= 1.1);
|
||||
|
||||
// Limit zoom
|
||||
treeState.scale = Math.min(Math.max(0.1, treeState.scale), 5);
|
||||
|
||||
treeState.pointX = e.clientX - xs * treeState.scale;
|
||||
treeState.pointY = e.clientY - ys * treeState.scale;
|
||||
|
||||
setTransform();
|
||||
});
|
||||
|
||||
// Pan (Mouse)
|
||||
treeTab.addEventListener('mousedown', (e) => {
|
||||
if (e.target.closest('.family-card') || e.target.closest('.fab')) return; // Don't drag if clicking card/button
|
||||
|
||||
e.preventDefault();
|
||||
treeState.startX = e.clientX - treeState.pointX;
|
||||
treeState.startY = e.clientY - treeState.pointY;
|
||||
treeState.panning = true;
|
||||
});
|
||||
|
||||
treeTab.addEventListener('mousemove', (e) => {
|
||||
if (!treeState.panning) return;
|
||||
e.preventDefault();
|
||||
treeState.pointX = e.clientX - treeState.startX;
|
||||
treeState.pointY = e.clientY - treeState.startY;
|
||||
setTransform();
|
||||
});
|
||||
|
||||
treeTab.addEventListener('mouseup', () => {
|
||||
treeState.panning = false;
|
||||
});
|
||||
|
||||
treeTab.addEventListener('mouseleave', () => {
|
||||
treeState.panning = false;
|
||||
});
|
||||
|
||||
function setTransform() {
|
||||
treeContainer.style.transform = `translate(${treeState.pointX}px, ${treeState.pointY}px) scale(${treeState.scale})`;
|
||||
}
|
||||
|
||||
// Initial center (approx)
|
||||
treeState.pointX = (window.innerWidth - 1000) / 2; // Assuming 1000px content width
|
||||
treeState.pointY = 50;
|
||||
setTransform();
|
||||
}
|
||||
|
||||
// Initialize PanZoom when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setupPanZoom();
|
||||
});
|
||||
|
|
|
|||
21
style.css
21
style.css
|
|
@ -377,3 +377,24 @@ input[type="radio"] {
|
|||
width: auto;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Pan and Zoom Styles */
|
||||
#tree-tab {
|
||||
overflow: hidden; /* Hide scrollbars, we use custom pan */
|
||||
position: relative;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
#tree-tab:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
#tree-container {
|
||||
transform-origin: 0 0; /* Zoom from top-left */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* Ensure it has size */
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
Loading…
Reference in a new issue