Add markers and track near home

This commit is contained in:
2025-11-19 02:40:15 -06:00
parent 2a81ab8b45
commit df14ce8ea0
6 changed files with 381 additions and 14 deletions

View File

@@ -26,7 +26,7 @@
<body>
<div id="map">
</div>
<script>var flightId = "910";</script>
<script>var flightId = "1";</script>
<script src="./MapViewLabelController.js"></script>
<script src="./02-script.js"></script>
</body>

View File

@@ -6,17 +6,17 @@ function getFlight(flightPath) {
}
// #region Map Section
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9yZGl0b3N0IiwiYSI6ImQtcVkyclEifQ.vwKrOGZoZSj3N-9MB6FF_A';
var map = new mapboxgl.Map({
let map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/outdoors-v9',
zoom: 12
});
var mapViewLabelController = new MapViewLabelController(map);
let mapViewLabelController = new MapViewLabelController(map);
// Get Mapbox map canvas container
var canvas = map.getCanvasContainer();
let canvas = map.getCanvasContainer();
map.addControl(new mapboxgl.NavigationControl());
// Overlay d3 on the map
var svg = d3.select(canvas).append("svg");
let svg = d3.select(canvas).append("svg");
// Load map and dataset
map.on('load', function () {
d3.json(`data/${flightId}_track.json`)
@@ -59,7 +59,7 @@ map.on('load', function () {
});
});
// Draw GeoJSON data with d3
var circles;
let circles;
function drawData(data) {
mapViewLabelController.drawLabels(data);
// Add circles

View File

@@ -1,9 +1,12 @@
"use strict";
// This class contains the logic for label creating for the mapview component
// It allows for clustering the labels and show a new lable when two or more labels overlap
class MapViewLabelController {
map;
canvas;
svg;
mapLabels;
// Takes a mapview map object and uses it to get the canvas container and create the initial svg element with d3.js
constructor(map) {
this.map = map;
this.canvas = map.getCanvasContainer();
@@ -11,10 +14,13 @@ class MapViewLabelController {
.attr("width", "100%").attr("height", "100%")
.attr("z-index", "10").style("position", "absolute").style("pointer-events", "none");
}
// Clears the current labels and redraws the labels for the geodata features passed as arguments
refreshLabels(geoData) {
d3.selectAll("g.label, g.labelclone").remove();
this.drawLabels(geoData);
}
// For each geodata feature executes the logic to append a new label to the svg elements.
// It also register the events to update the label position when the user interacts with the map.
drawLabels(geoData) {
this.mapLabels = this.svg.selectAll("g.label")
.data(geoData.features)
@@ -25,6 +31,7 @@ class MapViewLabelController {
const g = d3.select(nodes[i]);
this.appendLabels(d, g);
});
// Call the update function
this.updateLabelsPosition();
this.map.on("viewreset", () => this.updateLabelsPosition());
this.map.on("move", () => this.updateLabelsPosition());
@@ -92,9 +99,8 @@ class MapViewLabelController {
// Update d3 shapes' positions to the map's current state
updateLabelsPosition() {
if (this.mapLabels !== null && this.mapLabels !== undefined) {
// #region
const lblVerticalOffset = 0;
// Make clones of original labels.
const lblVerticalOffset = 4;
// The original cloned svg elements are removed and new ones are created
d3.selectAll("g.labelclone").remove();
this.mapLabels.each((_, i, nodes) => {
const clone = nodes[i].cloneNode(true);
@@ -104,16 +110,16 @@ class MapViewLabelController {
d3.select(nodes[i].parentNode).append(() => clone);
});
d3.selectAll("g.label").style("display", "none");
console.log(this.projectCoordinatesToPosition);
d3.selectAll("g.label, g.labelclone")
.attr("transform", (_, i, nodes) => {
const lon = Number(nodes[i].getAttribute("data-lon"));
const lat = Number(nodes[i].getAttribute("data-lat"));
const p = this.projectCoordinatesToPosition([lon, lat]);
const translateVal = `translate(${p.x}, ${p.y})`;
const translateVal = `translate(${p.x}, ${p.y + lblVerticalOffset})`;
console.log(translateVal);
return translateVal;
});
// Check if the label overlaps and if it does create a grouup with the overlaping labels.
const labelNodes = d3.selectAll("g.labelclone").nodes();
const labelGroups = [];
for (let i = 0; i < labelNodes.length; i++) {
@@ -147,10 +153,10 @@ class MapViewLabelController {
const match = /translate\(([^,]+),\s*([^)]+)\)/.exec(transform);
return { x: +match[1], y: +match[2] };
});
// Average position
// Calculate the new position
const avgX = coords.reduce((sum, c) => sum + c.x, 0) / coords.length;
const avgY = Math.min(...coords.map(c => c.y));
// Keep only the first label, update its text
// Create a new label with the combined text and append it to the svg elements.
const main = d3.select(group[0]);
const mergedLabel = {
type: "Feature",
@@ -174,6 +180,7 @@ class MapViewLabelController {
projectCoordinatesToPosition(c) {
return map.project(new mapboxgl.LngLat(+c[0], +c[1]));
}
// Detect if two labels overlap
isOverlapping(a, b) {
const recta = a.getBoundingClientRect();
const rectb = b.getBoundingClientRect();

122
data/1_markers.json Normal file
View File

@@ -0,0 +1,122 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Secundaria 18"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.350705,
25.7444119
]
}
},
{
"type": "Feature",
"properties": {
"name": "Casa"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.352194,
25.748501
]
}
},
{
"type": "Feature",
"properties": {
"name": "Casa Pera"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.351858,
25.746841
]
}
},
{
"type": "Feature",
"properties": {
"name": "Casa Florinda"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.349506,
25.747576
]
}
},
{
"type": "Feature",
"properties": {
"name": "Casa Amparo"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.350861,
25.749512
]
}
},
{
"type": "Feature",
"properties": {
"name": "Casa Eva"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.349927,
25.747692
]
}
},
{
"type": "Feature",
"properties": {
"name": "Iglesia Anunciacion a Maria"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.353306,
25.745824
]
}
},
{
"type": "Feature",
"properties": {
"name": "Preparatoria Emiliano Zapata"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.342630,
25.742958
]
}
},
{
"type": "Feature",
"properties": {
"name": "Oficinas Think"
},
"geometry": {
"type": "Point",
"coordinates": [
-100.295827,
25.735639
]
}
}
]
}

231
data/1_track.json Normal file
View File

@@ -0,0 +1,231 @@
{
"code": "Ok",
"routes": [
{
"legs": [
{
"steps": [],
"weight": 585.5,
"summary": "",
"duration": 585.5,
"distance": 6739.7
}
],
"weight_name": "routability",
"geometry": {
"coordinates": [
[-100.350796, 25.744135],
[-100.350683, 25.744123],
[-100.350598, 25.744113],
[-100.350535, 25.744233],
[-100.350393, 25.744479],
[-100.350116, 25.744941],
[-100.349923, 25.745281],
[-100.349744, 25.745599],
[-100.349568, 25.745918],
[-100.349464, 25.746092],
[-100.349367, 25.746264],
[-100.349194, 25.746569],
[-100.349027, 25.746864],
[-100.348909, 25.747057],
[-100.348829, 25.747201],
[-100.348638, 25.74755],
[-100.348449, 25.747876],
[-100.348256, 25.748207],
[-100.348114, 25.748478],
[-100.347893, 25.748875],
[-100.347576, 25.748624],
[-100.347318, 25.74842],
[-100.347195, 25.748322],
[-100.347127, 25.748261],
[-100.346977, 25.748109],
[-100.34619, 25.747253],
[-100.345741, 25.746781],
[-100.345155, 25.746148],
[-100.344665, 25.745614],
[-100.344591, 25.745533],
[-100.344145, 25.745069],
[-100.34405, 25.744978],
[-100.34385, 25.744778],
[-100.34357, 25.744505],
[-100.343451, 25.744386],
[-100.343064, 25.744023],
[-100.34275, 25.743739],
[-100.342687, 25.743693],
[-100.342619, 25.743657],
[-100.342554, 25.74364],
[-100.342447, 25.743628],
[-100.342366, 25.743618],
[-100.342263, 25.743588],
[-100.342182, 25.74355],
[-100.342089, 25.743486],
[-100.341848, 25.743267],
[-100.341744, 25.743161],
[-100.341632, 25.743041],
[-100.341538, 25.742918],
[-100.341403, 25.74273],
[-100.341252, 25.742505],
[-100.341156, 25.742389],
[-100.341001, 25.742159],
[-100.34093, 25.742045],
[-100.340617, 25.741557],
[-100.340546, 25.741455],
[-100.340326, 25.741132],
[-100.340216, 25.740972],
[-100.339986, 25.740629],
[-100.339663, 25.740159],
[-100.33938, 25.739751],
[-100.33935, 25.739684],
[-100.339263, 25.739529],
[-100.33852, 25.739438],
[-100.338152, 25.739384],
[-100.337778, 25.739338],
[-100.337395, 25.739284],
[-100.337025, 25.739245],
[-100.336628, 25.739189],
[-100.334907, 25.738979],
[-100.334816, 25.738968],
[-100.334752, 25.738961],
[-100.334332, 25.738908],
[-100.333329, 25.738783],
[-100.33258, 25.738667],
[-100.332444, 25.73865],
[-100.332337, 25.738679],
[-100.331496, 25.738584],
[-100.33116, 25.738554],
[-100.330866, 25.73852],
[-100.330543, 25.738477],
[-100.330287, 25.738442],
[-100.329974, 25.738381],
[-100.329674, 25.738344],
[-100.329589, 25.738334],
[-100.3286, 25.738211],
[-100.328072, 25.738142],
[-100.327893, 25.738118],
[-100.32766, 25.738088],
[-100.326706, 25.737963],
[-100.326499, 25.73794],
[-100.326044, 25.73788],
[-100.325953, 25.737869],
[-100.325775, 25.737845],
[-100.324831, 25.737748],
[-100.323924, 25.737675],
[-100.322977, 25.737614],
[-100.322515, 25.737585],
[-100.32137, 25.737511],
[-100.320841, 25.737478],
[-100.320709, 25.737469],
[-100.320011, 25.737425],
[-100.319943, 25.73738],
[-100.31855, 25.73731],
[-100.318278, 25.737296],
[-100.318239, 25.737293],
[-100.314824, 25.737078],
[-100.314517, 25.737059],
[-100.314394, 25.737052],
[-100.314081, 25.737033],
[-100.313921, 25.737023],
[-100.313888, 25.73702],
[-100.313588, 25.736997],
[-100.313428, 25.736985],
[-100.31281, 25.736937],
[-100.312292, 25.736897],
[-100.310893, 25.736788],
[-100.310858, 25.736696],
[-100.310809, 25.736644],
[-100.310799, 25.736564],
[-100.310787, 25.736479],
[-100.310826, 25.735984],
[-100.310871, 25.735311],
[-100.310905, 25.73477],
[-100.31089, 25.734676],
[-100.310907, 25.734643],
[-100.310913, 25.734611],
[-100.310908, 25.73458],
[-100.310895, 25.73455],
[-100.310873, 25.734525],
[-100.310843, 25.734505],
[-100.310806, 25.734493],
[-100.310767, 25.734492],
[-100.310729, 25.734501],
[-100.310696, 25.734519],
[-100.31067, 25.734546],
[-100.310654, 25.734578],
[-100.310649, 25.734604],
[-100.309482, 25.734971],
[-100.308077, 25.735414],
[-100.307762, 25.735516],
[-100.306666, 25.735876],
[-100.306407, 25.735956],
[-100.306075, 25.73606],
[-100.305983, 25.736091],
[-100.305844, 25.736134],
[-100.305495, 25.736244],
[-100.305188, 25.736349],
[-100.304468, 25.736577],
[-100.304301, 25.736635],
[-100.30406, 25.736704],
[-100.303982, 25.736724],
[-100.303937, 25.736726],
[-100.303869, 25.736715],
[-100.303697, 25.736633],
[-100.303598, 25.73647],
[-100.303518, 25.736326],
[-100.303455, 25.736242],
[-100.303405, 25.736201],
[-100.303342, 25.736154],
[-100.303243, 25.736086],
[-100.303155, 25.736051],
[-100.303062, 25.736024],
[-100.302795, 25.735926],
[-100.301759, 25.735616],
[-100.301402, 25.735514],
[-100.30124, 25.73549],
[-100.301104, 25.735495],
[-100.30097, 25.735528],
[-100.300786, 25.735594],
[-100.300635, 25.735647],
[-100.300255, 25.735804],
[-100.299813, 25.735987],
[-100.299626, 25.736073],
[-100.299483, 25.736155],
[-100.299413, 25.736186],
[-100.299282, 25.736223],
[-100.299077, 25.736235],
[-100.299005, 25.736242],
[-100.298422, 25.736264],
[-100.298056, 25.73628],
[-100.297967, 25.736277],
[-100.297866, 25.736277],
[-100.29752, 25.736243],
[-100.297362, 25.736215],
[-100.297215, 25.736222],
[-100.296998, 25.73617],
[-100.296681, 25.736077],
[-100.296356, 25.735979],
[-100.296104, 25.735878],
[-100.295836, 25.735752],
[-100.295764, 25.735719]
],
"type": "LineString"
},
"weight": 585.5,
"duration": 585.5,
"distance": 6739.7
}
],
"waypoints": [
{
"hint": "XIO2i12DtosbAAAARQAAABUAAAAAAAAAvqw2QcJA40EvnwlBAAAAABsAAABFAAAAFQAAAAAAAAC4dQAAtMQE-gfTiAGwxAT67NKIAQIATxEAAAAA",
"location": [-100.350796, 25.744135],
"name": "",
"distance": 3.017975125
},
{
"hint": "6KtbhO-rW4QPAAAACAAAAAAAAAA0AAAACnaHQRyPAUEAAAAAUNBnQg8AAAAIAAAAAAAAADQAAAC4dQAArJsF-ieyiAGSmwX6-bGIAQAAnxIAAAAA",
"location": [-100.295764, 25.735719],
"name": "Avenida de la Juventud",
"distance": 5.725131405
}
]
}

View File

@@ -1 +1,8 @@
https://router.project-osrm.org/route/v1/driving/-100.3508,25.7441078;-100.2982994,25.7354737?overview=full&geometries=geojson
https://router.project-osrm.org/route/v1/driving/-100.3508,25.7441078;-100.2982994,25.7354737?overview=full&geometries=geojson
https://router.project-osrm.org/route/v1/driving/<lon1>,<lat1>;<lon2>,<lat2>?steps=true
/route/v1/driving
/route/v1/walking
/route/v1/cycling