mirror of
https://github.com/smittix/intercept.git
synced 2026-06-09 14:41:55 -07:00
adding vector images for the towers and phones
This commit is contained in:
@@ -341,7 +341,100 @@ body {
|
||||
background: var(--bg-dark);
|
||||
}
|
||||
|
||||
/* Map markers */
|
||||
/* Map markers - Vector Icons */
|
||||
.gsm-marker {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gsm-marker svg {
|
||||
display: block;
|
||||
transition: filter 0.2s ease;
|
||||
}
|
||||
|
||||
/* Selection ring for selected towers */
|
||||
.selection-ring {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 2px solid rgba(255,255,255,0.6);
|
||||
border-radius: 50%;
|
||||
animation: selection-pulse 2s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes selection-pulse {
|
||||
0%, 100% {
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 0.6;
|
||||
}
|
||||
50% {
|
||||
transform: translate(-50%, -50%) scale(1.3);
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rogue tower pulse ring */
|
||||
.rogue-pulse-ring {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 2px solid var(--accent-red);
|
||||
border-radius: 50%;
|
||||
animation: rogue-pulse 1.5s ease-out infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes rogue-pulse {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) scale(0.8);
|
||||
opacity: 0.8;
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(2);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Device marker animations */
|
||||
.gsm-device {
|
||||
animation: device-fade-in 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes device-fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.device-fade-out {
|
||||
animation: device-fade-out 1s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes device-fade-out {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(0.3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Legacy circle marker support (fallback) */
|
||||
.tower-marker {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
@@ -1656,6 +1656,35 @@
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// GSM ICON DEFINITIONS
|
||||
// ============================================
|
||||
const GSM_ICONS = {
|
||||
tower: 'M12 2L11 3v5h2V3l-1-1zm-1 6v2H9v2h2v2H9v2h2v2H9v2h6v-2h-2v-2h2v-2h-2v-2h2v-2h-2V8h-2zm-3 4H6v8h2v-8zm8 0h-2v8h2v-8zM5 14H3v6h2v-6zm14 0h-2v6h2v-6z',
|
||||
device: 'M7 2v20h10V2H7zm2 2h6v12H9V4zm0 14h6v2H9v-2z'
|
||||
};
|
||||
|
||||
// Create marker icon with SVG
|
||||
function createGSMMarkerIcon(iconType, color, isSelected = false, isRogue = false) {
|
||||
const path = GSM_ICONS[iconType] || GSM_ICONS.tower;
|
||||
const size = iconType === 'tower' ? 24 : 20;
|
||||
const glowColor = isSelected ? 'rgba(255,255,255,0.9)' : color;
|
||||
const glowSize = isSelected ? '8px' : (isRogue ? '6px' : '4px');
|
||||
const pulseRing = isRogue && !isSelected ?
|
||||
'<div class="rogue-pulse-ring"></div>' : '';
|
||||
const selectionRing = isSelected ?
|
||||
'<div class="selection-ring"></div>' : '';
|
||||
|
||||
return L.divIcon({
|
||||
className: `gsm-marker gsm-${iconType}${isSelected ? ' selected' : ''}${isRogue ? ' rogue' : ''}`,
|
||||
html: `${pulseRing}${selectionRing}<svg width="${size}" height="${size}" viewBox="0 0 24 24" style="color: ${color}; filter: drop-shadow(0 0 ${glowSize} ${glowColor});">
|
||||
<path fill="currentColor" d="${path}"/>
|
||||
</svg>`,
|
||||
iconSize: [size, size],
|
||||
iconAnchor: [size/2, size/2]
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// TOWER HANDLING
|
||||
// ============================================
|
||||
@@ -1671,16 +1700,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const color = data.rogue ? '#e25d5d' : '#38c180';
|
||||
const isSelected = key === selectedTowerKey;
|
||||
|
||||
// Create or update marker
|
||||
if (!towerMarkers[key]) {
|
||||
// Create new marker
|
||||
const marker = L.circleMarker([data.lat, data.lon], {
|
||||
radius: 10,
|
||||
fillColor: data.rogue ? '#e25d5d' : '#38c180',
|
||||
color: data.rogue ? '#e25d5d' : '#38c180',
|
||||
weight: 2,
|
||||
opacity: 1,
|
||||
fillOpacity: 0.3
|
||||
// Create new marker with vector icon
|
||||
const marker = L.marker([data.lat, data.lon], {
|
||||
icon: createGSMMarkerIcon('tower', color, isSelected, data.rogue)
|
||||
});
|
||||
|
||||
marker.on('click', function() {
|
||||
@@ -1706,12 +1733,8 @@
|
||||
const marker = towerMarkers[key];
|
||||
marker.setLatLng([data.lat, data.lon]);
|
||||
|
||||
// Update color if rogue status changed
|
||||
const color = data.rogue ? '#e25d5d' : '#38c180';
|
||||
marker.setStyle({
|
||||
fillColor: color,
|
||||
color: color
|
||||
});
|
||||
// Update icon if rogue status or selection changed
|
||||
marker.setIcon(createGSMMarkerIcon('tower', color, isSelected, data.rogue));
|
||||
}
|
||||
|
||||
// Update towers list
|
||||
@@ -1785,11 +1808,22 @@
|
||||
}
|
||||
|
||||
function selectTower(key) {
|
||||
const prevSelected = selectedTowerKey;
|
||||
selectedTowerKey = key;
|
||||
const tower = towers[key];
|
||||
|
||||
if (!tower) return;
|
||||
|
||||
// Update marker icons for both previous and new selection
|
||||
[prevSelected, key].forEach(towerKey => {
|
||||
if (towerKey && towerMarkers[towerKey] && towers[towerKey]) {
|
||||
const t = towers[towerKey];
|
||||
const color = t.rogue ? '#e25d5d' : '#38c180';
|
||||
const isSelected = towerKey === selectedTowerKey;
|
||||
towerMarkers[towerKey].setIcon(createGSMMarkerIcon('tower', color, isSelected, t.rogue));
|
||||
}
|
||||
});
|
||||
|
||||
// Update selected tower panel
|
||||
const infoDiv = document.getElementById('selectedTowerInfo');
|
||||
infoDiv.innerHTML = `
|
||||
@@ -1864,15 +1898,9 @@
|
||||
const key = data.imsi || data.tmsi || `device_${Date.now()}`;
|
||||
devices[key] = data;
|
||||
|
||||
// Create device "blip" marker
|
||||
const marker = L.circleMarker([data.lat, data.lon], {
|
||||
radius: 5,
|
||||
fillColor: '#e25d5d',
|
||||
color: '#e25d5d',
|
||||
weight: 2,
|
||||
opacity: 1,
|
||||
fillOpacity: 0.8,
|
||||
className: 'device-blip'
|
||||
// Create device marker with vector icon
|
||||
const marker = L.marker([data.lat, data.lon], {
|
||||
icon: createGSMMarkerIcon('device', '#00d9ff', false, false)
|
||||
});
|
||||
|
||||
marker.bindPopup(`
|
||||
@@ -1884,7 +1912,17 @@
|
||||
marker.addTo(gsmMap);
|
||||
deviceMarkers[key] = marker;
|
||||
|
||||
// Remove marker after 5 seconds (pulse animation duration)
|
||||
// Fade out and remove marker after 4 seconds
|
||||
setTimeout(() => {
|
||||
if (deviceMarkers[key]) {
|
||||
const iconElement = deviceMarkers[key].getElement();
|
||||
if (iconElement) {
|
||||
iconElement.classList.add('device-fade-out');
|
||||
}
|
||||
}
|
||||
}, 4000);
|
||||
|
||||
// Remove marker after fade completes
|
||||
setTimeout(() => {
|
||||
if (deviceMarkers[key]) {
|
||||
gsmMap.removeLayer(deviceMarkers[key]);
|
||||
|
||||
Reference in New Issue
Block a user