Update: 2026-06-29 23:09:43
This commit is contained in:
160
loction_server/siro/ride/heatmap.html
Executable file
160
loction_server/siro/ride/heatmap.html
Executable file
@@ -0,0 +1,160 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ar" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>خريطة الكثافة الحرارية (Grid Heatmap) - OpenStreetMap</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
|
||||
<style>
|
||||
body { margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
|
||||
#map { height: 100vh; width: 100%; }
|
||||
.info-box {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 1000;
|
||||
background: white;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.2);
|
||||
max-width: 300px;
|
||||
}
|
||||
.legend {
|
||||
margin-top: 10px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.legend i {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
float: right;
|
||||
margin-left: 8px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="info-box">
|
||||
<h3>تحليل كثافة الرحلات</h3>
|
||||
<p>هذه الخريطة تقسم المنطقة إلى مربعات جغرافية وتحسب عدد الرحلات في كل مربع.</p>
|
||||
<div class="legend">
|
||||
<div><i style="background: #bd0026"></i> طلبات عالية جداً (+5)</div>
|
||||
<div><i style="background: #f03b20"></i> طلبات عالية (3-4)</div>
|
||||
<div><i style="background: #fd8d3c"></i> طلبات متوسطة (2)</div>
|
||||
<div><i style="background: #feb24c"></i> طلب واحد (1)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="map"></div>
|
||||
|
||||
<script>
|
||||
// 1. تهيئة الخريطة (مركزها دمشق مبدئياً)
|
||||
var map = L.map('map').setView([33.513, 36.276], 13);
|
||||
|
||||
// 2. إضافة طبقة OpenStreetMap
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}).addTo(map);
|
||||
|
||||
// 3. البيانات المستخرجة من ملفك (ride.json)
|
||||
// ملاحظة: قمت بوضع البيانات هنا لمحاكاتها، في الواقع سيقوم السكربت بطلبها من ملف heatmap.json
|
||||
var rawData = [
|
||||
{"type":"header","version":"5.2.2","comment":"Export to JSON plugin for PHPMyAdmin"},
|
||||
{"type":"database","name":"intaleq-ridesDB"},
|
||||
{"type":"table","name":"ride","database":"intaleq-ridesDB","data": [
|
||||
// ... تم نسخ عينة من بياناتك هنا لتعمل الصفحة ...
|
||||
{"start_location":"33.4323,36.2432"}, {"start_location":"34.68947,36.36329"},
|
||||
{"start_location":"33.5445,36.30571"}, {"start_location":"33.4323,36.24326"},
|
||||
{"start_location":"33.43222,36.24319"}, {"start_location":"33.51326,36.27646"},
|
||||
{"start_location":"33.50895,36.29209"}, {"start_location":"33.49631,36.3221"},
|
||||
{"start_location":"33.55463,36.32338"}, {"start_location":"33.53447,36.29727"},
|
||||
{"start_location":"33.5727,36.192"}, {"start_location":"33.52811,36.37998"},
|
||||
{"start_location":"33.54115,36.21846"}, {"start_location":"33.4323,36.24309"},
|
||||
{"start_location":"33.50312,36.25959"}, {"start_location":"33.52518,36.35682"},
|
||||
{"start_location":"33.51814,36.3119"}, {"start_location":"33.50142,36.27113"},
|
||||
{"start_location":"33.49593,36.30942"}, {"start_location":"33.55189,36.32245"},
|
||||
{"start_location":"33.5322,36.29513"}, {"start_location":"33.53994,36.22878"},
|
||||
{"start_location":"33.52441,36.28758"}, {"start_location":"33.46744,36.19679"},
|
||||
{"start_location":"33.52842,36.23082"}, {"start_location":"33.50236,36.27406"},
|
||||
{"start_location":"33.4323,36.24331"}, {"start_location":"33.51246,36.29807"}
|
||||
// (ملاحظة: البيانات هنا هي عينة لتعمل الصفحة، يمكنك استبدالها ببياناتك الكاملة)
|
||||
]}
|
||||
];
|
||||
|
||||
// في حال أردت استخدام بياناتك الكاملة، الصق محتوى المصفوفة "data" من ملفك داخل المتغير أدناه
|
||||
// سأقوم الآن باستخراج البيانات من الهيكل المعقد الذي أرسلته
|
||||
var rides = rawData[2].data;
|
||||
|
||||
// 4. خوارزمية الشبكة (Grid Algorithm)
|
||||
var grid = {};
|
||||
var precision = 0.005; // حجم المربع (تقريباً 500 متر). صغّر الرقم لـ 0.002 لدقة أعلى
|
||||
|
||||
rides.forEach(function(ride) {
|
||||
if(ride.start_location) {
|
||||
var coords = ride.start_location.split(',');
|
||||
var lat = parseFloat(coords[0]);
|
||||
var lng = parseFloat(coords[1]);
|
||||
|
||||
// استثناء القيم الصفرية أو البعيدة جداً
|
||||
if(lat > 32 && lat < 38 && lng > 35 && lng < 39) {
|
||||
|
||||
// حساب مفتاح الشبكة (تقريب الإحداثيات)
|
||||
// Math.floor(lat / precision) * precision -> يقوم بتوحيد الأرقام القريبة
|
||||
var gridLat = Math.floor(lat / precision) * precision;
|
||||
var gridLng = Math.floor(lng / precision) * precision;
|
||||
var key = gridLat.toFixed(3) + "_" + gridLng.toFixed(3);
|
||||
|
||||
if(!grid[key]) {
|
||||
grid[key] = {
|
||||
lat: gridLat,
|
||||
lng: gridLng,
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
grid[key].count++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 5. دالة تحديد اللون بناءً على العدد
|
||||
function getColor(d) {
|
||||
return d > 5 ? '#bd0026' : // أحمر داكن (حار جداً)
|
||||
d > 3 ? '#f03b20' : // أحمر
|
||||
d > 1 ? '#fd8d3c' : // برتقالي
|
||||
'#feb24c'; // أصفر (بارد)
|
||||
}
|
||||
|
||||
// 6. رسم المربعات على الخريطة
|
||||
var bounds = []; // لتحديد حدود الخريطة النهائية
|
||||
|
||||
for (var key in grid) {
|
||||
var zone = grid[key];
|
||||
|
||||
// تحديد زوايا المربع
|
||||
var southWest = [zone.lat, zone.lng];
|
||||
var northEast = [zone.lat + precision, zone.lng + precision];
|
||||
var zoneBounds = [southWest, northEast];
|
||||
|
||||
// رسم المستطيل
|
||||
L.rectangle(zoneBounds, {
|
||||
color: getColor(zone.count),
|
||||
weight: 1,
|
||||
fillOpacity: 0.6
|
||||
}).bindPopup("<b>عدد الرحلات:</b> " + zone.count)
|
||||
.addTo(map);
|
||||
|
||||
bounds.push(southWest);
|
||||
bounds.push(northEast);
|
||||
}
|
||||
|
||||
// 7. تحريك الكاميرا لتشمل كل النقاط
|
||||
if(bounds.length > 0) {
|
||||
map.fitBounds(bounds);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user