I am trying to use MySQL data to populate latitude, longitude as well as bearing, distance to waypoint across a route line drawn onto a MapBox map.
With the code below the route line is being drawn on the map, however only the first icon and first popup on the route are working while the rest do not display. The route line drawn on the map is displaying correctly, from start to end.
First I access the MySQL db and request the data.
<?php
$link = mysqli_connect( DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME ) or exit( mysqli_connect_error() );
mysqli_set_charset( $conn, 'utf8');
$query="SELECT * FROM table where field = '".$_SESSION["username"]."' ";
$result = mysqli_query($link,$query);
$row = mysqli_fetch_array($result);
?>
Then I create the geojson for the map to display the icons as well as popups by calling the MySQL as an array for populating .
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiY2xvbmc0MCIsImEiOiJjazNpeXV3a3MwY2Y4M2pxbGFybjZ5MTM4In0.HNQRjQR4y5V1koLlpenKUw';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [<?php echo $row['lat'];?>,<?php echo $row['lng'];?>],
zoom: 8
});
// Add geolocate control to the map.
map.addControl(
new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true
},
),'bottom-right'
)
;
map.on('load', function() {
map.addSource('route', {
'type': 'geojson',
'data': {
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'LineString',
'coordinates': [
<?php while ($data = $result->fetch_assoc()): ?>
[<?php echo $data['lat'];?>,<?php echo $data['lng'];?>],
<?php endwhile; ?>
[<?php echo $data['lat'];?>,<?php echo $data['lat'];?>]
]
}
}
});
map.addLayer({
'id': 'route',
'type': 'line',
'source': 'route',
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': '#333399',
'line-width': 4
}
});
});
//add markers
map.on('load', function() {
map.addSource('places', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
<?php while ($row = $result->fetch_assoc()): ?>
{
'type': 'Feature',
'properties': {
'description':
'<p>Waypoint main</p><img src="/assets/images/latitude.svg" alt="Latitude" width="25" height="25"> <strong>Latitude:</strong> <?php echo $row['lat'];?><br><br><img src="/assets/images/longitude.svg" alt="Longitude" width="25" height="25"> <strong>Longitude:</strong> <?php echo $row['lng'];?><br><br><img src="/assets/images/location.svg" alt="Next Way Point" width="25" height="25"> <strong>To Next Waypoint:</strong> <?php echo $row['from_waypoint'];?><br><br><img src="/assets/images/direction.svg" alt="Bearing" width="25" height="25"> <strong>Bearing:</strong> <?php echo $row['bearing'];?><br><br><img src="/assets/images/total%20distance.svg" alt="Total Distance" width="25" height="25"> <strong>From start:</strong> <?php echo $row['from_start'];?><br><br>',
'icon': 'information'
'iconSize': '15'
},
'geometry': {
'type': 'Point',
'coordinates': [<?php echo $row['lat'];?>, <?php echo $row['lng'];?>]
}
},
<?php endwhile; ?>
{
'type': 'Feature',
'properties': {
'description':
'<p>Waypoint</p>Latitude:</strong><?php echo $row['lat'];?><br><strong>Longitude:</strong><?php echo $row['lng'];?><strong>To Next Waypoint:</strong><br><strong>Bearing:</strong><br><strong>From start:</strong><?php echo $row['froms_tart'];?><br><br>',
'icon': 'information'
'iconSize': '15'
},
'geometry': {
'type': 'Point',
'coordinates': [<?php echo $row['lat'];?>, <?php echo $row['lng'];?>]
}
}
]
}
});
// Add a layer showing the places.
map.addLayer({
'id': 'places',
'type': 'symbol',
'source': 'places',
'layout': {
'icon-image': 'information',
'icon-size': 0.25,
'icon-allow-overlap': true
}
});
// When a click event occurs on a feature in the places layer, open a popup at the location of the feature, with description HTML from its properties.
map.on('click', 'places', function(e) {
var coordinates = e.features[0].geometry.coordinates.slice();
var description = e.features[0].properties.description;
// Ensure that if the map is zoomed out such that multiple copies of the feature are visible, the popup appears over the copy being pointed to.
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML(description)
.addTo(map);
});
// Change the cursor to a pointer when the mouse is over the places layer.
map.on('mouseenter', 'places', function() {
map.getCanvas().style.cursor = 'pointer';
});
// Change it back to a pointer when it leaves.
map.on('mouseleave', 'places', function() {
map.getCanvas().style.cursor = '';
});
});
map.addControl(new mapboxgl.NavigationControl(), 'bottom-right');
</script>
Sample of the data in the table, tab delimited.
uuid user direction from last way point from start lng lat depth trip_id date
117 5ad9bbdadd3401837eae1409c77a4179 null 0 0 37.28505100000001 13.528828999999973 null 1 2020-07-12 15:56:00
118 5ad9bbdadd3401837eae1409c77a4180 59 89 89 37.28546875000001 13.5296875 null 1 2020-07-12 15:56:00
119 5ad9bbdadd3401837eae1409c77a4181 107 58 147 37.2853125 13.5303125 null 1 2020-07-12 15:56:00
120 5ad9bbdadd3401837eae1409c77a4182 158 75 222 37.2846875 13.530625 null 1 2020-07-12 15:56:00
121 5ad9bbdadd3401837eae1409c77a4183 180 35 257 37.284375 13.530625 null 1 2020-07-12 15:56:00
122 5ad9bbdadd3401837eae1409c77a4184 -141 355 612 37.281875 13.528125 null 1 2020-07-12 15:56:00
What am I doing incorrectly that the rest of the icons on the route are not displaying and neither are the popups?
The site can be viewed at www.med-sailing.com/navigation_test.php or production www.med-sailing.com/navigation.php (site access is free and just requires registration with an email address).
Most of the documentation relates to how to use PDO to extract the data from MySQL and present via PHP, the below relates how to pull out the array from MySQL and present it as geojson in PHP. The problem was that I needed to wrap all of the geojson in PHP, once the change was made everything worked perfectly.
<?php while ($row = $result->fetch_assoc()): ?>
{
"type": "Feature",
"properties": {
"description": "<p>Waypoint main</p><img src=\"/assets/images/latitude.svg\" alt=\"Latitude\" width=\"25\" height=\"25\"> <strong>Latitude:</strong> <?php echo $row["lat"];?><br><br><img src=\"/assets/images/longitude.svg\" alt=\"Longitude\" width=\"25\" height=\"25\"> <strong>Longitude:</strong> <?php echo $row["lng"];?><br><br><img src=\"/assets/images/location.svg\" alt=\"Next Way Point\" width=\"25\" height=\"25\"> <strong>To Next Waypoint:</strong> <?php echo $row["from_waypoint"];?><br><br><img src=\"/assets/images/direction.svg\" alt=\"Bearing\" width=\"25\" height=\"25\"> <strong>Bearing:</strong> <?php echo $row["bearing"];?><br><br><img src=\"/assets/images/total%20distance.svg\" alt=\"Total Distance\" width=\"25\" height=\"25\"> <strong>From start:</strong> <?php echo $row["from_start"];?><br><br>",
"icon": "information",
"iconSize": "15"
},
"geometry": {
"type": "Point",
"coordinates": [<?php echo $row["lat"];?>, <?php echo $row["lng"];?>]
}
}<?php
// only if there is another line
if ($row = $result->fetch_assoc()) echo ","
?>
<?php endwhile; ?>