Search code examples
mapboxmapbox-gl

Building information for MapBox using MySql data


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">&nbsp;&nbsp;<strong>Latitude:</strong>&nbsp;<?php echo $row['lat'];?><br><br><img src="/assets/images/longitude.svg" alt="Longitude" width="25" height="25">&nbsp;&nbsp;<strong>Longitude:</strong>&nbsp;<?php echo $row['lng'];?><br><br><img src="/assets/images/location.svg" alt="Next Way Point" width="25" height="25">&nbsp;<strong>To Next Waypoint:</strong>&nbsp;<?php echo $row['from_waypoint'];?><br><br><img src="/assets/images/direction.svg" alt="Bearing" width="25" height="25">&nbsp;&nbsp;<strong>Bearing:</strong>&nbsp;<?php echo $row['bearing'];?><br><br><img src="/assets/images/total%20distance.svg" alt="Total Distance" width="25" height="25">&nbsp;&nbsp;<strong>From start:</strong>&nbsp;<?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).


Solution

  • 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\">&nbsp;&nbsp;<strong>Latitude:</strong>&nbsp;<?php echo $row["lat"];?><br><br><img src=\"/assets/images/longitude.svg\" alt=\"Longitude\" width=\"25\" height=\"25\">&nbsp;&nbsp;<strong>Longitude:</strong>&nbsp;<?php echo $row["lng"];?><br><br><img src=\"/assets/images/location.svg\" alt=\"Next Way Point\" width=\"25\" height=\"25\">&nbsp;<strong>To Next Waypoint:</strong>&nbsp;<?php echo $row["from_waypoint"];?><br><br><img src=\"/assets/images/direction.svg\" alt=\"Bearing\" width=\"25\" height=\"25\">&nbsp;&nbsp;<strong>Bearing:</strong>&nbsp;<?php echo $row["bearing"];?><br><br><img src=\"/assets/images/total%20distance.svg\" alt=\"Total Distance\" width=\"25\" height=\"25\">&nbsp;&nbsp;<strong>From start:</strong>&nbsp;<?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; ?>