feat: add animated custom markers for SPBU and implement centralized application logic in app.js
This commit is contained in:
@@ -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', () => {
|
||||
|
||||
Reference in New Issue
Block a user