UNPKG

bbox2heatmap

Version:

Crawling Flickr's geotagged photographs and drawing a heatmap

415 lines (402 loc) 19.4 kB
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <title>Heatmap Viewer for Flickr Geotagged Photographs</title> <style> body, html { margin: 0; padding: 0; height: 100%; } body { font-family: sans-serif; } body * { font-weight: 200; } h1 { position: absolute; background: white; padding: 10px; } #map { height: 100%; } #thumb { border: 3px solid black; z-index: 10000; width: 81px; height: 81px; background-color: beige; position: absolute; top: 100%; left: 0px; margin-top: -81px; } h1 { position: absolute; background: black; color: white; padding: 10px; font-weight: 200; z-index: 10000; } #btn { position: absolute; background: black; color: white; padding: 10px; font-weight: 200; z-index: 10000; left: 100%; width: 300px; margin-left: -300px; } /*Thanks https://gist.github.com/comp615/2288108*/ .leaflet-div-icon { background: transparent !important; border: none !important; color: white !important; } .leaflet-marker-icon .number { position: relative; top: -37px; font-size: 12px; width: 25px; text-align: center; } </style> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" /> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <!--link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script--> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.8.0/leaflet.min.js" integrity="sha512-TL+GX2RsOUlTndpkgHVnSQ9r6zldqHzfyECrdabkpucdFroZ3/HAhMmP2WYaPjsJCoot+0McmdPOLjmmicG9qg==" crossorigin="anonymous" referrerpolicy="no-referrer" ></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.8.0/leaflet.min.css" integrity="sha512-oIQ0EBio8LJupRpgmDsIsvm0Fsr6c3XNHLB7at5xb+Cf6eQuCX9xuX8XXGRIcokNgdqL1ms7nqbQ6ryXMGxXpg==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <!--link rel="stylesheet" href="https://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" /--> <!--script src="https://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script--> <!--script src="lib/heatmap.js"></script--> <script src="https://cdnjs.cloudflare.com/ajax/libs/heatmap.js/2.0.0/heatmap.min.js" integrity="sha512-FpvmtV53P/z7yzv1TAIVH7PNz94EKXs5aV6ts/Zi+B/VeGU5Xwo6KIbwpTgKc0d4urD/BtkK50IC9785y68/AA==" crossorigin="anonymous" referrerpolicy="no-referrer" ></script> <!--script src="lib/leaflet-heatmap.js"></script--> <script src="https://cdn.jsdelivr.net/npm/leaflet-heatmap@1.0.0/leaflet-heatmap.min.js"></script> </head> <body> <div id="btn"> <div id="tag"></div> </div> <div id="thumb"><img /></div> <div id="map"></div> <script> const dataset={bbox2heatmap0result}; const search={bbox2heatmap0search}; const bboxraw={bbox2heatmap0bbox}; </script> <script> // Thanks https://gist.github.com/comp615/2288108 let photos = []; let photoIdx = 0; let photoMarker = null; let map; function changePhoto() { if (photos.length <= photoIdx) { photoIdx = 0; } if (photoMarker != null) { map.removeLayer(photoMarker); } $('#thumb>img').attr('src', photos[photoIdx++].url); photoMarker = L.marker([photos[photoIdx++].lat, photos[photoIdx++].lng]).addTo(map); setTimeout(changePhoto, 1000); } L.NumberedDivIcon = L.Icon.extend({ options: { // EDIT THIS TO POINT TO THE FILE AT http://www.charliecroom.com/marker_hole.png (or your own marker) iconUrl: 'lib/marker.png', number: '', shadowUrl: null, iconSize: new L.Point(25, 41), iconAnchor: new L.Point(13, 41), popupAnchor: new L.Point(0, -33), className: 'leaflet-div-icon', }, createIcon: function () { var div = document.createElement('div'); var img = this._createImg(this.options['iconUrl']); var numdiv = document.createElement('div'); numdiv.setAttribute('class', 'number'); numdiv.innerHTML = this.options['number'] || ''; div.appendChild(img); div.appendChild(numdiv); this._setIconStyles(div, 'icon'); return div; }, //you could change this to add a shadow like in the normal marker if you really wanted createShadow: function () { return null; }, }); var layer; var cells = 50; window.onload = function () { const bbox = [ [bboxraw[1], bboxraw[0]], [bboxraw[3], bboxraw[2]], ]; console.log(search, bbox); var baseLayer = L.tileLayer('https://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png', { attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>', maxZoom: 18, }); var src = { max: 45, data: [], }; //var dataset = JSON.parse(e.target.result); var east = Math.max(dataset.bbox[0], dataset.bbox[2]); var west = Math.min(dataset.bbox[0], dataset.bbox[2]); var north = Math.max(dataset.bbox[1], dataset.bbox[3]); var south = Math.min(dataset.bbox[1], dataset.bbox[3]); var center = { lat: west + (east - west) / 2, lng: south + (north - south) / 2 }; var grid = {}; var track = {}; if (dataset.track) { dataset.track.every(function (item) { track[item] = []; return true; }); } document.getElementById('tag').innerHTML = 'Search: ' + dataset.search; var range = Math.min(north - south, east - west) / cells; dataset.data.forEach(function (item) { //console.log(item); photos.push({ url: item.url_sq, lat: item.latitude, lng: item.longitude, }); if (item.latitude && item.longitude) { var lat = parseFloat(item.latitude); var lng = parseFloat(item.longitude); var sn = Math.floor((lat - south) / range); var we = Math.floor((lng - west) / range); if (grid[sn + '.' + we]) { grid[sn + '.' + we]++; } else { grid[sn + '.' + we] = 1; } var d = { lat: lat, lng: lng, count: 1, }; if (dataset.track) { Object.keys(track).every(function (id) { if (id == item.owner) { track[id].push(item); return false; } else { return true; } }); } src.data.push(d); } }); var n = []; for (var idx in grid) { n.push(grid[idx]); } n = n.sort(function cp(val1, val2) { return val2 - val1; }); //console.log(track); if (dataset.track) { Object.keys(track).every(function (id) { var traj = track[id].sort(function (p1, p2) { return p1.datetaken - p2.datetaken; }); traj.every(function (item, n) { var marker = new L.Marker(new L.LatLng(parseFloat(item.latitude), parseFloat(item.longitude)), { icon: new L.NumberedDivIcon({ number: n + 1 }), }); marker.on('click', function () { //console.log(item.datetaken + '\t' + item.url_z); }); marker.addTo(map); return true; }); return true; }); } src.max = Math.round(n[Math.round(n.length / 10)]); var cfg = { radius: range, maxOpacity: 0.8, scaleRadius: true, useLocalExtrema: false, latField: 'lat', lngField: 'lng', valueField: 'count', }; console.log('[Draw heatmap] max=' + src.max + ' ,range=' + range); var heatmapLayer = new HeatmapOverlay(cfg); heatmapLayer.setData(src); map = new L.Map('map', { center: new L.LatLng(center.lat, center.lng), zoom: 4, layers: [baseLayer, heatmapLayer], }); console.log('BBOX', JSON.stringify(bbox)); map.fitBounds(bbox); map.on('zoomend', function () { //console.log("zoom"); map.removeLayer(heatmapLayer); var east = Math.max(dataset.bbox[0], dataset.bbox[2]); var west = Math.min(dataset.bbox[0], dataset.bbox[2]); var north = Math.max(dataset.bbox[1], dataset.bbox[3]); var south = Math.min(dataset.bbox[1], dataset.bbox[3]); var rangeDataset = Math.min(north - south, east - west) / cells; var b = map.getBounds(); var rangeMap = Math.min(b.getNorth() - b.getSouth(), b.getEast() - b.getWest()) / cells; var new_cfg = { radius: Math.min(rangeDataset, rangeMap), maxOpacity: 0.8, scaleRadius: true, useLocalExtrema: true, latField: 'lat', lngField: 'lng', valueField: 'count', }; heatmapLayer = new HeatmapOverlay(new_cfg); map.addLayer(heatmapLayer); heatmapLayer.setData(src); }); changePhoto(); }; /* document.getElementById('files').addEventListener('change', function (evt) { var reader = new FileReader(); reader.onload = function (e) { map.removeLayer(layer); var src = { max: 45, data: [], }; var dataset = JSON.parse(e.target.result); var east = Math.max(dataset.bbox[0], dataset.bbox[2]); var west = Math.min(dataset.bbox[0], dataset.bbox[2]); var north = Math.max(dataset.bbox[1], dataset.bbox[3]); var south = Math.min(dataset.bbox[1], dataset.bbox[3]); var cells = 50; var grid = {}; var track = {}; if (dataset.track) { dataset.track.every(function (item) { track[item] = []; return true; }); } document.getElementById('tag').innerHTML = 'Search: ' + dataset.search; var range = Math.min(north - south, east - west) / cells; dataset.data.forEach(function (item) { if (item.latitude && item.longitude) { var lat = parseFloat(item.latitude); var lng = parseFloat(item.longitude); var sn = Math.floor((lat - south) / range); var we = Math.floor((lng - west) / range); if (grid[sn + '.' + we]) { grid[sn + '.' + we]++; } else { grid[sn + '.' + we] = 1; } var d = { lat: lat, lng: lng, count: 1, }; if (dataset.track) { Object.keys(track).every(function (id) { if (id == item.owner) { track[id].push(item); return false; } else { return true; } }); } src.data.push(d); } }); var n = []; for (var idx in grid) { n.push(grid[idx]); } n = n.sort(function cp(val1, val2) { return val2 - val1; }); console.log(track); if (dataset.track) { Object.keys(track).every(function (id) { var traj = track[id].sort(function (p1, p2) { return p1.datetaken - p2.datetaken; }); traj.every(function (item, n) { var marker = new L.Marker(new L.LatLng(parseFloat(item.latitude), parseFloat(item.longitude)), { icon: new L.NumberedDivIcon({ number: n + 1 }), }); marker.on('click', function () { console.log(item.datetaken + '\t' + item.url_z); }); marker.addTo(map); return true; }); return true; }); } src.max = Math.round(n[Math.round(n.length / 10)]); var cfg = { radius: range, maxOpacity: 0.8, scaleRadius: true, useLocalExtrema: false, latField: 'lat', lngField: 'lng', valueField: 'count', }; console.log('[Draw heatmap] max=' + src.max + ' ,range=' + range); layer = new HeatmapOverlay(cfg); map.addLayer(layer); layer.setData(src); map.fitBounds([ [dataset.bbox[1], dataset.bbox[0]], [dataset.bbox[3], dataset.bbox[2]], ]); }; reader.readAsText(evt.target.files[0]); }); */ </script> </body> </html>