Reputation: 123
Having a problem where Mapbox using Leaflet is not displaying correctly in a modal.
The map and marker are in the upper left and the rest of the tiles are blank.
I have tried the code directly in a page and not a modal and it works...
<style>
#mapid { height: 300px; }
</style>
<div id="mapid"></div>
<script>
var mymap = L.map('mapid').setView([<?= $return['latitude']; ?>, <?= $return['longitude']; ?>], 13);
//var mymap = L.Map('mapid', { center: new L.LatLng(<?= $return['latitude']; ?>, <?= $return['longitude']; ?>]), zoom: 15, layers: [nexrad], zoomControl: true });
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=<?= $MapBoxToken ?>', {
attribution: '© <a href="http://mapbox.com">Mapbox</a>, © <a href="http://openstreetmap.org">OpenStreetMap</a>',
maxZoom: 20,
id: 'mapbox.streets',
accessToken: '<?= $MapBoxToken ?>'
}).addTo(mymap);
var marker = L.marker([<?= $return['latitude']; ?>, <?= $return['longitude']; ?>]).addTo(mymap);
</script>
Upvotes: 4
Views: 5878
Reputation: 123
The problem seem to with bootstap modal.
Needed to add map.invalidateSize(); but within "shown.bs.modal", as per ghybs suggestion.
$('#myModal').on('shown.bs.modal', function() {
map.invalidateSize();
});
Note that the "map" in map.invalidateSize(); needs to be replace with the varable assigned in "var map = L.map()". In my original code in this post it was:
var mymap = L.map('mapid').setView([<?= $return['latitude']; ?>, <?= $return['longitude']; ?>], 13);
so I added:
$('#modalID').on('shown.bs.modal', function() {
mymap.invalidateSize();
});
Upvotes: 1
Reputation: 53280
As explained in the linked post, having the map work when the browser window is resized is just a symptom of the issue. Leaflet listens to browser window resize event, and reads again the map viewport dimensions when it occurs, so that it can properly display tiles and center the view.
Under the hood, Leaflet simply calls map.invalidateSize()
on the resize event.
So the proper solution for your case is NOT to have the browser window be resized, but to call map.invalidateSize()
.
And do that NOT after your map loads, but after your modal is opened, so that the map viewport now has its final dimensions.
Since you added the Bootstrap tag to your question, I guess your modal is built using Bootstrap. In that case, you can listen to the "shown.bs.modal"
event:
var map = L.map('map').setView([48.86, 2.35], 11);
L.marker([48.86, 2.35]).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Comment out the below code to see the difference.
$('#myModal').on('shown.bs.modal', function() {
map.invalidateSize();
});
<!-- Bootstrap assets -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<!-- Leaflet assets -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Launch demo modal that contains the map container.
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
<!-- map container -->
<div id="map" style="height: 180px"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Upvotes: 11