feat: add animated custom markers for SPBU and implement centralized application logic in app.js

This commit is contained in:
z0rayy
2026-06-08 21:59:05 +07:00
parent a090cc7934
commit d3c9de3a34
4 changed files with 175 additions and 58 deletions
+46 -7
View File
@@ -147,6 +147,34 @@
.legend-panel h3 { font-size: 11px; font-weight: 700; color: var(--clr-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 10px; }
.legend-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; color: var(--clr-text); font-size: 12px; }
.legend-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
/* ---- Custom Marker ---- */
.custom-marker {
display: flex; justify-content: center; align-items: center;
}
.marker-halo {
position: absolute;
width: 40px; height: 40px;
border-radius: 50%;
animation: pulse 2s infinite ease-out;
}
.marker-halo.spbu { background: rgba(34, 197, 94, 0.5); }
.marker-halo.spbu-off { background: rgba(245, 158, 11, 0.5); }
.marker-halo.user { background: rgba(59, 130, 246, 0.5); }
.marker-icon-inner {
position: relative; z-index: 2;
width: 28px; height: 28px;
background: white; border-radius: 50%;
box-shadow: 0 2px 8px rgba(0,0,0,0.5);
display: flex; justify-content: center; align-items: center;
font-size: 14px;
}
@keyframes pulse {
0% { transform: scale(0.5); opacity: 1; }
100% { transform: scale(1.5); opacity: 0; }
}
</style>
</head>
<body>
@@ -275,9 +303,19 @@
if (filterText && !spbu.nama.toLowerCase().includes(filterText.toLowerCase()) && !spbu.no_spbu.toLowerCase().includes(filterText.toLowerCase())) return;
const lat = parseFloat(spbu.latitude), lng = parseFloat(spbu.longitude);
if (isNaN(lat) || isNaN(lng)) return;
const color = spbu.status === '24jam' ? '#22c55e' : '#f59e0b';
const marker = L.circleMarker([lat, lng], { radius: 7, fillColor: color, color: '#fff', weight: 2, opacity: 1, fillOpacity: 0.9 })
.bindPopup('<strong>' + spbu.nama + '</strong><br>No: ' + spbu.no_spbu + '<br>Status: ' + (spbu.status === '24jam' ? '✅ 24 Jam' : '⏰ Tidak 24 Jam'))
const is24 = spbu.status === '24jam';
const haloClass = is24 ? 'spbu' : 'spbu-off';
const customIcon = L.divIcon({
className: 'custom-marker',
html: `<div class="marker-halo ${haloClass}"></div><div class="marker-icon-inner">⛽</div>`,
iconSize: [28, 28],
iconAnchor: [14, 14],
popupAnchor: [0, -14]
});
const marker = L.marker([lat, lng], { icon: customIcon })
.bindPopup('<strong>' + spbu.nama + '</strong><br>No: ' + spbu.no_spbu + '<br>Status: ' + (is24 ? '✅ 24 Jam' : '⏰ Tidak 24 Jam'))
.addTo(spbuLayer);
bounds.push([lat, lng]);
});
@@ -335,10 +373,11 @@
renderSPBU(spbu.nama.toLowerCase(), true);
};
const userIcon = L.icon({
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41]
const userIcon = L.divIcon({
className: 'custom-marker',
html: `<div class="marker-halo user"></div><div class="marker-icon-inner">📍</div>`,
iconSize: [28, 28],
iconAnchor: [14, 14]
});
document.getElementById('btn-location').addEventListener('click', () => {