Leaflet - Gray stripes after panning - ionic-framework

EDIT
This question is not a duplicate of How to get a leaflet map canvas to have a 100% height? as for the obvious reason, that you can see my map spanning the 100% height (compare the attribution on my picture being in the gray zone, while the container of the other question obviously ends before the blank zone. Also i can identify the size of my container spanning the 100% of the parent container in the developer tools. Just take a look at my css and and a very close look at the picture and maybe at leaftlet if you don't know how it works.)
Original
I use leaflet 1.5.1 in ionic 3.
After panning the map a bit, oftentimes the contents for gray parts are not being loaded (no network requests/traffic indicated in my browsers dev tools) and i am left with gray parts/stripes in the map as in the picture (the gray horizontal stripe below).
When i pan a lot further the missing map parts are loaded, but sometimes not (especially in iOS).
My map page's HTML using my map component (below)
<map style="height: 100%; width: 100%;">
The map component's HTML
<div id='map'></div>
The component's scss file
map {
#map{
height:100%;
width: 100%;
}
}
And here the component's typescript which creates the map
this.map = L.map('map', {
center: L.LatLng(center.latitude, center.longitude),
zoom: 13,
attribution: Attribution,
tap: false
});
//Add OSM Layer
L.tileLayer("https://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png", { attribution: Attribution }).addTo(this.map);
this.map.setView([center.latitude, center.longitude], 14);
Any hints on what i'm doing wrong?

The solution was to trigger a resizing event via window.dispatchEvent(new Event('resize')) every time the user enters the tab page holding all the tabs including the map tab.
The map is reacting to this by adjusting itself to the "new" size.

Related

Full map not working unless I resize browser window [duplicate]

I am using tabs to display clear content, but one of them stopped downloading well since it is in the data-toggle tab. It is a Leaflet map.
Here is the code :
Navbar code :
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#home">Données principales</a></li>
<li><a data-toggle="tab" href="#carte">Carte</a></li>
</ul>
<div class="tab-content">
<div id="home" class="tab-pane fade in active">Lorem ipsum</div>
<div id="carte" class="tab-pane fade"> **//see script below\\** </div>
</div>
Script :
<div id="carteBenef"></div>
<script type="text/javascript">
$(document).ready(function () {
var map = new L.Map('carteBenef');
var cloudmadeUrl = 'http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png',
subDomains = ['otile1', 'otile2', 'otile3', 'otile4'],
cloudmadeAttrib = 'Data, imagery and map information provided by MapQuest, OpenStreetMap and contributors, CC-BY-SA';
var cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttrib, subdomains: subDomains});
var iades = new L.LatLng(<?php echo $beneficiaire->latitude . ', ' . $beneficiaire->longitude; ?>)
map.addLayer(cloudmade).setView(iades, 15);
var benefLocation = new L.LatLng(<?php echo $beneficiaire->latitude . ', ' . $beneficiaire->longitude; ?>);
var benef = new L.Marker(benefLocation);
map.addLayer(benef);
benef.bindPopup("<?php echo htmlspecialchars($beneficiaire->nom) . ' ' . htmlspecialchars($beneficiaire->prenom); ?>").openPopup();
});
</script>
The map was appearing well before I put it in the tab, does someone have an idea why it does not work now? Thank you =)
Welcome to SO!
If your Leaflet map suddenly works correctly after you resize your browser window, then you experience the classic "map container size not valid at map initialization": in order to work correctly, Leaflet reads the map container size when you initialize the map (L.map("mapContainerId")).
If your application hides that container (typically through CSS display: none;, or some framework tab / modal / whatever…) or later changes its dimensions, Leaflet will not be aware of the new size. Hence it will not render correctly. Typically, it downloads tiles only for the fraction of the container it thinks is shown. This can be a single tile in the top left corner in the case of a container that was entirely hidden at map initialization time.
This mistake often arises when embedding the map container in a "tab" or "modal" panel, possibly using popular frameworks (Bootstrap, Angular, Ionic, etc.).
Leaflet listens to browser window resize event, and reads again the container size when it happens. This explains why the map suddenly works on window resizing.
You can also manually trigger this update by calling map.invalidateSize() when the tab panel is displayed (e.g. add a listener on the tab button click), at least the first time the container is rendered with its correct dimensions.
As for implementing the tab button click listener, perform a new search on SO on that topic: you should have plenty resources available for that matter, for most of the popular frameworks.
First, thank you #ghybs for your good explanation on why the Leaflet maps are not shown properly in these cases.
For those who tried unsuccessfully the #ghybs's answer, you should try to resize your browser instead of calling a method of the map object :
window.dispatchEvent(new Event('resize'));
As #MarsAndBack said, this fix may cause issues on pan/animation/etc features that Leaflet's invalidateSize provides.
I have this problem because i used modal bootstarp. and it not solved anyway. i tried map.invalidateSize() and window.dispatchEvent(new Event('resize')); but not fixed.
finaly it fixed by this:
$('#map-modal').on('shown.bs.modal', function(event) {});
'shown.bs.modal' event means when modal is completely load and not any confuse on size, now inside that write your codes.
For those like me weren't able to solve the challenge with the precious #ghybs explanation (map.invalidateSize()) and were able to do it with #gangai-johann one, there's still a chance you may do it the right way. Put your invalidate instruction inside a setTimeout, as it may be too early to dispatch that instruction.
setTimeout(() => {
this.$refs.mymap.mapObject.invalidateSize()
}, 100)
Refer to https://stackoverflow.com/a/56364130/4537054 answer for detailed instructions.

react-leflet map layer repeating

I have a map, but it repeats. I would like it to stop repeating, and get only one map. How do I do this?
<MapContainer
className='h-[700px] w-[700px] float-right mr-10 mt-10'
center={[51.505, -0.09]} zoom={5} scrollWheelZoom={true}>
<TileLayer
noWrap={true}
url="/allmap.jpg"
/>
</MapContainer>
I see that you added in the URL a path to image url="/allmap.jpg". as it's an image you can inspect on the TileLayer after it's rendered. see on the right side the class which contains this image as background-image add to that class the following.
.tile-layer-class {
background-repeat: no-repeat;
background-size: cover;
}
UPDATE:
The problem was that the image was not shown. because there was a style from leaflet.css hide the image to show. you can override that style by using the below class.
.leaflet-container {
overflow: unset <= or by using !important as well if that didn't reflect.
}
The problem is not related to styling at all. what I figured out that the image is not only rendered just one time in the dom but it's gets rendered for 4 images tags. you can inspect the image and you will see that there're 4 img tags in the dom.
I think you will need to find out the reason for why there're 4 images rendered in the dom.
I tried to be honest to do my best. but I'm not familiar with Next.js

Responsiveness issues with multiple charts using Chartjs, the class "chartjs-size-monitor" is only getting applied for only one chart

I am using ChartJs library to create the Line Chart. I have two Charts on the page. I need to resize the Charts on opening of Side Menu. I have used a container div to wrap the canvas element and that worked fine when I only had one chart on the page.
Now when I have two Chart on the page, on opening of Side Menu, only one Chart is getting resized. The observation that I had is that probably resize event is only getting applied to only of the Charts and that's why the div with the class "chartjs-size-monitor" is getting applied to the first Chart. Please note that this div is being created by the ChartJs internally.
below is the class "chartjs-size-monitor" which get's applied as an adjacent tag of canvas tag.
<div class="chartjs-size-monitor"><div class="chartjs-size-monitor-expand"><div class="">
</div></div>
<div class="chartjs-size-monitor-shrink"><div class="">
</div></div></div>
As a result of this tag, the class "chartjs-render-monitor" is getting applied to the canvas tag thus making it responsive.
<canvas id="chart_name1" class="chartjs-render-monitor" style="display:
block; height: 582px; width: 1165px;" width="1747" height="873"></canvas>
However the div element with class "chartjs-size-monitor" is not getting applied to the second Chart.
Kindly let me know what could be done as a workaround in case of having multiple ChartJs Charts on the same page.
FYI, I have already tried making changes to the option of Charts like making
responsive: true,
maintainAspectRatio: false

Map view leaflet on SilverStripe

I work on SilverStripe 4 using leaflet and my cards present these gray lines:
I tried a lot of stuff on CSS and JS but no change. Can someone advise how to supress these gray lines?
The grey lines are caused by your site css adding a border to your images.
If you inspect the marker img element you will see there is some img css that adds a border. Something like the following:
img {
border: 4px solid #d7d7d7;
}
Here is a demo recreating the issue:
https://jsfiddle.net/5jbgyeq0/
A few options to fix the problem are:
Remove that css
Make the css more specific so it doesn't apply to the map images
Add some css to remove borders on map pane images
Here is an example of some css to remove borders on map pane images:
.leaflet-map-pane img {
border: none;
}

How to init map correctly when hidden?

I have a map, which is displayed or hidden depending on a button click.
I init the map while it is hidden, add layer, add markers, and call fitBounds() for the markers.
My problem is that when the map is hidden, fitBounds doesn't work. After switching to visible, the map is shown but fully zoomed out. When I call fitBounds again, the map is shown correctly.
How do I know when the map is ready? I tried mapReady, but it is also called when the map is hidden.
Is there another way?
Thanks!
How do I know when the map is ready?
FWIW, it is indeed when the map.whenReady(callback) executes your callback.
Your issue is probably not about the map not being ready (as you figured out, the map is ready even when hidden), but in the fact that it is originally hidden, hence it (the map container) does not have its final size. It needs that size (height and width) as it impacts your map.fitBounds().
You probably just need to call map.invalidateSize() and re-perform your fitBounds once you show your map.
See also: Data-toggle tab does not download Leaflet map
You might easily create valid div with width & height. Also you need to setup it as absolute.
Then, add this div to relative one, which is displayed. That is all.
<div style="display: block; position: relative; overflow: hidden;">
<div style="display: absolute; width: 100px; height: 100px; left: -1000px; top: -1000px;" id="map"></div>
</div>
That might be enough