Customize openstreetmap tilelayer render with leaflet - leaflet

I'm currently struggling with an issue. I'm developing an app with reactJS and I wanted to display a map with a marker that the user could move and so on. Therefore, I used leaflet with the react-leaflet package and I used openstreetmap as TileLayer. Until here, everything is OK.
The thing is that I would like to be able to customize the render of the OpenStreetMap (like put the roads in red, forrest in another green, not display sea border and so on...) so that it would suit more with the design of my website.
I tried to find some solution on the web, but nothing convinced me a lot or maybe I didn't understand them well. I think there is a way to do that with Leaflet VectorGrid https://leaflet.github.io/Leaflet.VectorGrid/vectorgrid-api-docs.html
but it is not very clear for me.
I specify that I want to use OpenStreetMap and not solutions such as mapbox. I think it is kind of useless but here is my code to display my map to show you how I did it :
<Map center={position} zoom={12}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
<Marker
position={position ? position : TOULOUSE_GPS_LOCATION}
draggable={true}
onDragend={handleMarkerPositionChange}
>
<Popup>
Vous pouvez déplacer le marqueur afin <br /> d'ajuster au mieux votre position
</Popup>
</Marker>
</Map>
</Wrapper>
Thanks in advance for you responses !

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.

How to use Next JS IMAGE inside material ui card media

I am using Next JS and Material UI together in my project. for Image optimization, I would like to use the Next JS Image component.
currently, my card media looks like below. I am getting the image URL row.image.url from an API call and assigning it to the image prop of the CardMedia component
<CardMedia
className={classes.cardMedia}
image={row.image.url}/>
But I would like to take the advantage of the Next JS Image component for the optimization and lazy loading but couldn't able to see a way to fit this.
import Image from 'next/image'
Did anyone face this type of requirement?
Appreciate your help
Thanks
Venk
You can do it like this:
<CardMedia className={classes.cardMedia} title="Your title">
<div style={{ position: 'relative', width: '100%', height: '100%' }}>
<Image src={row.image.url} layout="fill" objectFit="cover" />
</div>
</CardMedia>
Check this answer for more info

Using the new Next.js Image component with Material UI

In Material UI the components that display images have a parameter for the image. eg:
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
In Next.js v10 there is a new Image component that automatically scales images: https://nextjs.org/docs/api-reference/next/image 
Has anyone figured out how to use the new Image component with Material UI?
I am able to use it like this and it works well. I hope it will be helpful.
<Avatar className={className}>
<Image src={src || placeholder} alt={alt} layout="fill" />
</Avatar>
import image_1 from "/static/images/avatar/1.jpg" //locate image
then just replace
src="/static/images/avatar/1.jpg"
to
src={image_1.src}

TomTom tile layer not included in leaflet map

Currently working on an app (map) where I would like to use the Tom Tom tile layers on top of Leaflet. Due to Leaflet's documentation I would like to stick to Leaflet, rather than Tom Tom. I was successful at setting up the map using the Tom Tom approach, but I couldnt get the tile layer to be added using the leaflet library.
I cant see what Im doing wrong. Could anyone help please?
According to the leaflet tutorial the code should work like this: https://leafletjs.com/examples/quick-start/
The Tom Tom tile map API url can be generated from: https://developer.tomtom.com/content/maps-api-explorer#/Vector/get_map__versionNumber__tile__layer___style___zoom___X___Y__pbf
`
// Creating a map instance with its center set to London with a zoom of 13
var mymap = L.map('map').setView([51.505, -0.09], 13);
// Accessing the tile layer from the TOMTOM site
L.tileLayer('https://api.tomtom.com/map/1/tile/basic/main/1/0/0.pbf?key=MY_API_KEY', {
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
//id: 'mapbox.streets',
//accessToken: 'your.mapbox.access.token'
}).addTo(mymap);
<!DOCTYPE html>
<html>
<head>
<!-- Bootstrap css and scripts -->
<link rel="stylesheet" href="./00_Local_Bootstrap\css\bootstrap.css">
<script src="./00_Local_Bootstrap\js\bootstrap.js"></script>
<script src="./00_Local_Bootstrap\jquery_3_4_1\jquery_3_4_1.js"></script>
<!-- Leaflet css and scripts -->
<link rel="stylesheet" type="text/css" href="./Leaflet\leaflet.css" />
<script src="./Leaflet\leaflet.js"></script>
<style media="screen">
#map {
width: 50vw;
height: 50vh;
}
</style>
</head>
<body>
<!-- Map Import-->
<div class="container">
<p>Here is the map</p>
<div id='map'></div>
<!-- Mymap script -->
<script src="./welcome_page_leaflet.js"></script>
</div>
</body>
</html>
`
The leaflet documentation is using Mapbox, which is why they refer to the corresponding access token and id. Thats why I commented it out.
The map doesnt load the tiles and I only get a blank screen where the map should be. What am I missing?
Looks like you are trying to display vector tiles (with PBF extension) through Leaflet Tile Layer, which is meant for raster tiles.
Tom Tom provides raster tiles as well: https://developer.tomtom.com/maps-api/maps-api-documentation-raster/raster-tile

Polymer 1.0 paper-dialog shows extremely compressed

I can't seem to get the paper-dialog to show up correctly all of the time. It will show correctly once then it will show up compressed the next time when I click on it to the point that it looks like a line. Unfortunately, I am unable to add a picture of it since this is my first question.
I have removed my styling sheets from this element but could the other styling sheets of my other element be causing this problem? Any direction of what I should look at would be really helpful.
I setup this paper dialog with the following:
<paper-dialog id='addressDialog'
opened="{{addressDialogOpened}}"
no-cancel-on-outside-click
no-cancel-on-esc-key
entry-animation="slide-from-right-animation"
exit-animation="scale-down-animation">
<div>
<template is="dom-if" if="{{newAddressDialog}}">
<h2>Add an Address</h2>
</template>
<template is="dom-if" if="{{editAddressDialog}}">
<h2>Edit Address Information</h2>
</template>
<hr>
</div>
It has a series of template repeats in it as well. I was reading about the paper dialog and it says that it has space for a header, content area, and buttons. Do I always have to set it up this way in order for it to work?
Additional solution is to add position: fixed; into your paper-dialog style like:
:host paper-dialog { position: fixed; }
So the only way that I saw to fix this terrible problem was to use a style of "min-height" and some percentage of the page. After I included this in my paper-dialog elements the popups were showing perfectly.