heatmaps-composelink / index.html
sombochea's picture
please replace locations to Phnom Penh City and random facilities and trash bins locations. - Follow Up Deployment
056b25b verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Facilities & Trash Bins Heatmap</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBybAUlzNzGZG6-eqpjCnLJWOBfNPsmNaU&libraries=visualization"></script>
<style>
.custom-radio input:checked + label {
background-color: #3b82f6;
color: white;
}
.heatmap-gradient {
background: linear-gradient(to right,
rgba(0, 0, 255, 0.5),
rgba(0, 255, 0, 0.5),
rgba(255, 255, 0, 0.5),
rgba(255, 165, 0, 0.5),
rgba(255, 0, 0, 0.5));
}
.map-container {
height: 70vh;
}
@media (max-width: 640px) {
.map-container {
height: 50vh;
}
}
</style>
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<header class="mb-8 text-center">
<h1 class="text-3xl md:text-4xl font-bold text-blue-800 mb-2">Facilities & Trash Bins Heatmap</h1>
<p class="text-gray-600 max-w-2xl mx-auto">
Visualize the density of public facilities and trash bins in your area.
The heatmap shows concentrations with warmer colors indicating higher density.
</p>
</header>
<div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8">
<div class="p-4 md:p-6 flex flex-col md:flex-row justify-between items-center gap-4">
<div class="flex-1">
<h2 class="text-xl font-semibold text-gray-800 mb-2">Map Controls</h2>
<div class="flex flex-wrap gap-4">
<div class="flex items-center space-x-2">
<div class="custom-radio">
<input type="radio" id="show-all" name="map-type" checked class="hidden">
<label for="show-all" class="px-3 py-1 rounded-full border border-blue-500 text-blue-500 cursor-pointer transition-colors">
Show All
</label>
</div>
<div class="custom-radio">
<input type="radio" id="show-facilities" name="map-type" class="hidden">
<label for="show-facilities" class="px-3 py-1 rounded-full border border-green-500 text-green-500 cursor-pointer transition-colors">
Facilities Only
</label>
</div>
<div class="custom-radio">
<input type="radio" id="show-trash" name="map-type" class="hidden">
<label for="show-trash" class="px-3 py-1 rounded-full border border-red-500 text-red-500 cursor-pointer transition-colors">
Trash Bins Only
</label>
</div>
</div>
</div>
</div>
<div class="flex items-center gap-2">
<div class="h-4 w-4 rounded-full bg-blue-500"></div>
<span class="text-sm text-gray-600">Facilities</span>
<div class="h-4 w-4 rounded-full bg-red-500 ml-2"></div>
<span class="text-sm text-gray-600">Trash Bins</span>
</div>
</div>
<div class="relative">
<div id="map" class="map-container w-full"></div>
<div class="absolute bottom-4 left-4 bg-white p-2 rounded-lg shadow-md">
<div class="flex items-center mb-1">
<span class="text-xs mr-2">Low</span>
<div class="heatmap-gradient w-32 h-4 rounded"></div>
<span class="text-xs ml-2">High</span>
</div>
<p class="text-xs text-gray-600">Heatmap intensity scale</p>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
<div class="bg-white p-6 rounded-xl shadow-lg">
<h3 class="text-xl font-semibold text-gray-800 mb-4">Facilities Density</h3>
<div class="h-64" id="facilities-chart"></div>
<p class="text-sm text-gray-600 mt-2">
This chart shows the distribution of public facilities across different areas.
</p>
</div>
<div class="bg-white p-6 rounded-xl shadow-lg">
<h3 class="text-xl font-semibold text-gray-800 mb-4">Trash Bins Density</h3>
<div class="h-64" id="trash-chart"></div>
<p class="text-sm text-gray-600 mt-2">
This chart shows the concentration of trash bins in different zones.
</p>
</div>
</div>
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="p-6">
<h3 class="text-xl font-semibold text-gray-800 mb-4">Data Summary</h3>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Count</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Density</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Area Coverage</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">Public Facilities</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">248</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">High</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">85%</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">Trash Bins</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">176</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Medium</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">72%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
// Sample data - in a real app, this would come from an API
const facilitiesData = [
{lat: 11.5664, lng: 104.9182}, // Central Market
{lat: 11.5464, lng: 104.9382}, // Russian Market
{lat: 11.5564, lng: 104.9282}, // Independence Monument
{lat: 11.5764, lng: 104.9182}, // Wat Phnom
{lat: 11.5364, lng: 104.9482}, // Chroy Changvar
{lat: 11.5664, lng: 104.9082}, // Riverside
{lat: 11.5464, lng: 104.9182}, // BKK1
{lat: 11.5564, lng: 104.9382}, // Toul Tom Poung
{lat: 11.5864, lng: 104.9282}, // Phsar Thmey
{lat: 11.5264, lng: 104.9282}, // Chbar Ampov
{lat: 11.5664, lng: 104.9482}, // Boeung Keng Kang
{lat: 11.5464, lng: 104.9082}, // Daun Penh
{lat: 11.5764, lng: 104.9382}, // Olympic Stadium
{lat: 11.5364, lng: 104.9182}, // Koh Pich
{lat: 11.5564, lng: 104.9082}, // Sisowath Quay
{lat: 11.5664, lng: 104.9282}, // Central Business District
{lat: 11.5464, lng: 104.9282}, // Street 51
{lat: 11.5564, lng: 104.9182}, // Royal Palace
{lat: 11.5364, lng: 104.9382}, // Tonle Bassac
{lat: 11.5764, lng: 104.9082} // Phnom Penh International Airport
];
const trashData = [
{lat: 11.5554, lng: 104.9272}, // Near Independence Monument
{lat: 11.5554, lng: 104.9272}, // Near Independence Monument
{lat: 11.5554, lng: 104.9272}, // Near Independence Monument
{lat: 11.5574, lng: 104.9292}, // Near Wat Langka
{lat: 11.5544, lng: 104.9252}, // Near Sihanouk Blvd
{lat: 11.5584, lng: 104.9262}, // Near Street 51
{lat: 11.5534, lng: 104.9292}, // Near Street 63
{lat: 11.5564, lng: 104.9312}, // Near Street 310
{lat: 11.5594, lng: 104.9252}, // Near Street 154
{lat: 11.5524, lng: 104.9282}, // Near Street 19
{lat: 11.5554, lng: 104.9232}, // Near Riverside
{lat: 11.5574, lng: 104.9322}, // Near Russian Market
{lat: 11.5544, lng: 104.9302}, // Near Street 135
{lat: 11.5564, lng: 104.9242}, // Near Street 13
{lat: 11.5584, lng: 104.9282}, // Near Street 51
{lat: 11.5534, lng: 104.9272}, // Near Street 21
{lat: 11.5554, lng: 104.9252}, // Near Street 178
{lat: 11.5574, lng: 104.9302} // Near Street 63
];
let map, facilitiesHeatmap, trashHeatmap;
let allHeatmapData = [...facilitiesData.map(p => new google.maps.LatLng(p.lat, p.lng)),
...trashData.map(p => new google.maps.LatLng(p.lat, p.lng))];
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
zoom: 13,
center: { lat: 11.5564, lng: 104.9282 },
mapTypeId: "roadmap",
styles: [
{
featureType: "poi",
elementType: "labels",
stylers: [{ visibility: "off" }]
}
]
});
// Create heatmap layers
facilitiesHeatmap = new google.maps.visualization.HeatmapLayer({
data: facilitiesData.map(p => new google.maps.LatLng(p.lat, p.lng)),
map: map,
radius: 30,
gradient: [
'rgba(0, 0, 255, 0)',
'rgba(0, 0, 255, 1)',
'rgba(0, 255, 255, 1)',
'rgba(0, 255, 0, 1)',
'rgba(255, 255, 0, 1)',
'rgba(255, 165, 0, 1)',
'rgba(255, 0, 0, 1)'
]
});
trashHeatmap = new google.maps.visualization.HeatmapLayer({
data: trashData.map(p => new google.maps.LatLng(p.lat, p.lng)),
map: map,
radius: 25,
gradient: [
'rgba(255, 0, 0, 0)',
'rgba(255, 0, 0, 0.5)',
'rgba(255, 69, 0, 0.8)',
'rgba(255, 140, 0, 1)',
'rgba(255, 165, 0, 1)'
]
});
// Set up radio button controls
document.getElementById('show-all').addEventListener('change', function() {
facilitiesHeatmap.setMap(map);
trashHeatmap.setMap(map);
});
document.getElementById('show-facilities').addEventListener('change', function() {
facilitiesHeatmap.setMap(map);
trashHeatmap.setMap(null);
});
document.getElementById('show-trash').addEventListener('change', function() {
facilitiesHeatmap.setMap(null);
trashHeatmap.setMap(map);
});
// Simple chart visualization
renderSimpleCharts();
}
function renderSimpleCharts() {
// This is a simplified chart - in a real app you'd use a charting library
const facilitiesChart = document.getElementById('facilities-chart');
const trashChart = document.getElementById('trash-chart');
// Create simple bar charts using divs
facilitiesChart.innerHTML = `
<div class="h-full flex items-end gap-1">
<div class="flex-1 bg-blue-500 rounded-t" style="height: 70%"></div>
<div class="flex-1 bg-blue-500 rounded-t" style="height: 85%"></div>
<div class="flex-1 bg-blue-500 rounded-t" style="height: 60%"></div>
<div class="flex-1 bg-blue-500 rounded-t" style="height: 45%"></div>
<div class="flex-1 bg-blue-500 rounded-t" style="height: 75%"></div>
<div class="flex-1 bg-blue-500 rounded-t" style="height: 90%"></div>
<div class="flex-1 bg-blue-500 rounded-t" style="height: 65%"></div>
</div>
`;
trashChart.innerHTML = `
<div class="h-full flex items-end gap-1">
<div class="flex-1 bg-red-500 rounded-t" style="height: 50%"></div>
<div class="flex-1 bg-red-500 rounded-t" style="height: 75%"></div>
<div class="flex-1 bg-red-500 rounded-t" style="height: 40%"></div>
<div class="flex-1 bg-red-500 rounded-t" style="height: 85%"></div>
<div class="flex-1 bg-red-500 rounded-t" style="height: 60%"></div>
<div class="flex-1 bg-red-500 rounded-t" style="height: 45%"></div>
<div class="flex-1 bg-red-500 rounded-t" style="height: 70%"></div>
</div>
`;
}
// Initialize the map when the window loads
window.onload = initMap;
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=sombochea/heatmaps-composelink" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>