How to load a KML from Google Drive in Leaflet? - javascript

I am trying to display a KML file (loading it directly from Google Drive, e.g. https://drive.google.com/file/d/1Ngi_nLWEYt-aCzX0dGioa8bP3K-UbUNP/view?usp=sharing) on a map using Leaflet. With the code below,this Error triggers:
Uncaught (in promise) Error: Bounds are not valid.
at i.fitBounds (leaflet.js:5)
at index.html:45
What is wrong?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"> </meta>
<title>Map</title>
<link rel = "stylesheet" href = "lib/leaflet.css"/>
<script src = "lib/leaflet.js"></script>
<script src = "lib/L.KML.js"></script>
<style type="text/css">
#pozadina{background-image: linear-gradient(to right,lightblue, rgb(36, 112, 226));}
#map{
height: 720px;
width: 86%;
padding-left: 7%;
padding-right: 7%;
}
#naslov{
color: rgb(15, 15, 199);
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
}
</style>
</head>
<body id="pozadina">
<h1 id="naslov">Map</h1>
<div id = "map"></div>
<script>
// Make basemap
const map = new L.Map('map', { center: new L.LatLng(44.786568, 20.448921), zoom: 11 });
const osm = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
map.addLayer(osm);
// Load kml file
fetch("https://cors-anywhere.herokuapp.com/" +"https://drive.google.com/file/d/1Ngi_nLWEYt-aCzX0dGioa8bP3K-UbUNP/view?usp=sharing")
.then(res => res.text())
.then(kmltext => {
const parser = new DOMParser();
const kml = parser.parseFromString(kmltext, 'text/xml');
const track = new L.KML(kml);
map.addLayer(track);
console.log(track.getBounds());
map.fitBounds(track.getBounds()); //here is a problem
});
</script>
</body>
</html>

The KML file you are linking to (https://drive.google.com/file/d/1Ngi_nLWEYt-aCzX0dGioa8bP3K-UbUNP/view?usp=sharing) is on Google Drive, and you are pointing at the Share link. That share link loads and HTML page for the file, and does not download the file itself. You need a URL that directly downloads the actual KML file. The Google Drive interface does not provide this type of direct link, but there are instructions out there that will show you the necessary URL pattern to construct such a link. Alternatively, you could re-host the KML file on some other service which provides an easy direct link to the file itself.

Related

How to change language in mapbox

I need to change the language of the mapbox in javascript, I only see the below code in the documentation
map.setLayoutProperty('country-label', 'text-field', ['get', 'name_de'])
but this line of code will only change the country names but I need everything ( city, town, ...etc)
Based on your mapbox style, there will be different text layers. For dark-v9, these are the available text layers.
country-label
state-label
settlement-label
settlement-subdivision-label
airport-label
poi-label
water-point-label
water-line-label
natural-point-label
natural-line-label
waterway-label
road-label
Using the code snippet that you mentioned in the question on the above layers, you should be able to change the language.
map.setLayoutProperty('country-label', 'text-field', ['get', 'name_de'])
Or you can use mapbox-language-plugin to change the language of all the possible layers. Here is the working example of the plugin.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Change a map's language</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.1/mapbox-gl.js'></script>
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-language/v0.10.1/mapbox-gl-language.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.1/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
#buttons {
width: 90%;
margin: 0 auto;
}
.button {
display: inline-block;
position: relative;
cursor: pointer;
width: 20%;
padding: 8px;
border-radius: 3px;
margin-top: 10px;
font-size: 12px;
text-align: center;
color: #fff;
background: #ee8a65;
font-family: sans-serif;
font-weight: bold;
}
</style>
<div id='map'></div>
<ul id="buttons">
<li id='button-fr' class='button'>French</li>
<li id='button-ru' class='button'>Russian</li>
<li id='button-de' class='button'>German</li>
<li id='button-es' class='button'>Spanish</li>
</ul>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibXVyYWxpcHJhamFwYXRpIiwiYSI6ImNrMHA1d3VjYzBna3gzbG50ZjR5b2Zkb20ifQ.guBaIUcqkTdYHX1R6CM6FQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v9',
center: [16.05, 48],
zoom: 2.9
});
mapboxgl.setRTLTextPlugin('https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.1.0/mapbox-gl-rtl-text.js');
var mapboxLanguage = new MapboxLanguage({
defaultLanguage: 'en'
});
map.addControl(mapboxLanguage);
document.getElementById('buttons').addEventListener('click', function(event) {
var language = event.target.id.substr('button-'.length);
map.setStyle(mapboxLanguage.setLanguage(map.getStyle(), language));
});
</script>
</body>
</html>
Ref: https://blog.mapbox.com/how-to-localize-your-maps-in-mapbox-gl-js-da4cc6749f47
Here is a code I have found helpful for me from github mapbox here
map.getStyle().layers.forEach(function(thisLayer){
if(thisLayer.type == 'symbol'){
map.setLayoutProperty(thisLayer.id, 'text-field', ['get','name_ja'])
}
})
I have modified it to
map.getStyle().layers.forEach(function(thisLayer){
console.log(thisLayer);
if(thisLayer.id.indexOf('-label')>0){
console.log('change '+thisLayer.id);
map.setLayoutProperty(thisLayer.id, 'text-field', ['get','name_fr'])
}
});
But otherwise you'll have to change the different labels yourself as mentionned by murli-prajapati
Of course, change 'name_xx' by your own language
such as:
map.setLayoutProperty('country-label', 'text-field', ['get','name_fr']);
map.setLayoutProperty('state-label', 'text-field', ['get','name_fr']);
map.setLayoutProperty('settlement-label', 'text-field', ['get','name_fr']);
map.setLayoutProperty('settlement-subdivision-label', 'text-field', ['get','name_fr']);
The only thing that helped me is a cycle placed in load event:
map.on('load', function() {
let labels = [ 'country-label', 'state-label',
'settlement-label', 'settlement-subdivision-label',
'airport-label', 'poi-label', 'water-point-label',
'water-line-label', 'natural-point-label',
'natural-line-label', 'waterway-label', 'road-label' ];
labels.forEach(label => {
map.setLayoutProperty(label, 'text-field', 'get','name_ru']);
});
})
Language plugin and other stuff didn't work.
Belatedly, you could use this plugin to change the display language according to the user locale.
https://github.com/mapbox/mapbox-gl-language
For example:
mapboxgl.accessToken = 'YOUR_ACCESS_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v10',
center: [-77.0259, 38.9010],
zoom: 9
});
const language = new MapboxLanguage();
map.addControl(language);
After trying all the solutions in this thread with streets-v12 I found non of them gave me what I needed.
The plug-in doesn’t work at all, and #Mike & #honey59 solutions semi-work, I still found many components not translated.
What did work best for me was to use Mapbox’s studio to create custom map and change the language there to all the components & layers (guide: https://docs.mapbox.com/help/troubleshooting/change-language/).
And on my site I know when user is viewing the page on a specific language, so I just needed to map the languages to their custom maps URLs.
I know it’s not the most “technical” dynamic solution, but I found it to be the most complete one

Using MapBox for Geolocation in html

I would like to display the address on dynamics CRM using MapBox API, i
have used Google API and it works perfectly, but now i would like to display it using map box.
I have looked at the forward geo-location feature of Mapbox but it's not yet clear.
So my variable my address variable will be coming from a field.
e.g var address = "6 Antares Drive, Ottawa, Ontario K2E 8A2, Canada";
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Add a geocoder</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.43.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.43.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.1.1/mapbox-gl-geocoder.min.js'></script>
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.1.1/mapbox-gl-geocoder.css' type='text/css' />
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibGF3aXgxMCIsImEiOiJjamJlOGE1bmcyZ2V5MzNtcmlyaWRzcDZlIn0.ZRQ73zzVxwcADIPvsqB6mg';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-79.4512, 43.6568],
zoom: 13
});
var address = "6 Antares Drive, Ottawa, Ontario K2E 8A2, Canada";
var geocoder = new MapboxGeocoder({ accessToken: mapboxgl.accessToken });
geocoder.query(address); // how do i search and display this address
map.addControl(geocoder);
//map.addControl(new MapboxGeocoder({
// accessToken: mapboxgl.accessToken
//}));
</script>
</body>
</html>
How can the address be displayed similar to that of google map on the Html Page.
mapbox-gl-geocoder is a geocoder control for Mapbox GL JS, it's intended to provide a the user interface, that is, an input search box for searching on top of the Mapbox Geocoding API.
If you already have your query and just want to display that location on the map you're better to use the Mapbox JavaScript SDK with geocodeForward, see https://github.com/mapbox/mapbox-sdk-js#installation.
The Console.Log was very helpful, I found out that the data.features.center returns the coordinates which was all what i needed . the full code is below
<html>
<head>
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.43.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.43.0/mapbox-gl.css' rel='stylesheet' />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body style="word-wrap:break-word;">
<div id='map'></div>
<script src='https://unpkg.com/mapbox#1.0.0-beta9/dist/mapbox-sdk.min.js'></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibGF3aXgxMCIsImEiOiJjamJlOGE1bmcyZ2V5MzNtcmlyaWRzcDZlIn0.ZRQ73zzVxwcADIPvsqB6mg';
console.log(mapboxgl.accessToken);
var client = new MapboxClient(mapboxgl.accessToken);
console.log(client);
var address = 't5h 0k7'
var test = client.geocodeForward(address, function(err, data, res) {
// data is the geocoding result as parsed JSON
// res is the http response, including: status, headers and entity properties
console.log(res);
console.log(res.url);
console.log(data);
var coordinates = data.features[0].center;
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v10',
center: coordinates,
zoom: 14
});
new mapboxgl.Marker()
.setLngLat(coordinates)
.addTo(map);
});
</script>
</body>
</html>

Uncaught Type error in Google console

While creating a basic google map I AM getting the following error: Uncaught typeError: Cannot read property 'maps' of undefined
Index.html file is:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBKNPX_2z_JDWcyADlzzFk9JChR4TwhZLQ"
async defer></script>
</script>
<script src="script.js"></script>
</body>
</html>
the script .js file is:
(function(window,google)
{
//maps options
var options={
center: {
lat:"0",
lng:"0"
},
zoom:0
},
//maps
element=document.getElementById('map-canvas'),
map = new google.maps.Map(element,options);
}(window,window.google));
The css file is:
html {
height: 100%;
}
body {
height:100%;
padding: 0;
margin: 0;
}
#map-canvas {
height: 100%;
}
The error is telling you the Google Maps Javascript API v3 is not loaded when you are trying to run code that depends on it.
You are loading the Google Maps Javascript API v3 using "async defer", but loading your script inline, you need to either defer both or load both without the "async defer".

example of mapbox not working with another .geojson file

I'm trying to test mapbox, but I am stuck in trying to visualize some polygons coming from a .geojson file.
Here's my code:
(needs Allow-Control-Allow-Origin Chrome Plugin to work properly).
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Point in polygon</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.mapbox.com/mapbox.js/v2.2.1/mapbox.js'></script>
<link href='https://api.mapbox.com/mapbox.js/v2.2.1/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
.state {
position:absolute;
top:10px;
right:10px;
z-index:1000;
}
.state strong {
background:#404040;
color:#fff;
display:block;
padding:10px;
border-radius:3px;
}
</style>
<!--
This example requires jQuery to load the file with AJAX.
You can use another tool for AJAX.
This pulls the file airports.csv, converts into into GeoJSON by autodetecting
the latitude and longitude columns, and adds it to the map.
Another CSV that you use will also need to contain latitude and longitude
columns, and they must be similarly named.
-->
<script src='https://code.jquery.com/jquery-1.11.0.min.js'></script>
<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-pip/v0.0.2/leaflet-pip.js'></script>
<div id='map'></div>
<div id='state' class='state'></div>
<script>
L.mapbox.accessToken = 'pk.eyJ1IjoicmljcmljdWNpdCIsImEiOiIyODdkMTk4YmY5YTllYWQ1ZTk5MWQ5NTEwYmIwMjQ3OSJ9.a2bQbD9hl6dOCI7Om1BcwQ';
var state = document.getElementById('state');
var map = L.mapbox.map('map', 'mapbox.emerald')
.setView([38, -95], 4);
$.ajax({
//url: 'https://www.mapbox.com/mapbox.js/assets/data/us-states.geojson', // correctly show U.S.A
url: 'http://playground.nothingisclear.net/simplified_LW_2015.geojson', // should show some areas in south-west Germany (Baden-Wuttemberg)
dataType: 'json',
success: function load(d) {
console.log(d);
var states = L.geoJson(d).addTo(map);
}
});
</script>
</body>
</html>
My problem is that my geojson –showing polygons in a south west region of Germany– doesn't work (http://playground.nothingisclear.net/simplified_LW_2015.geojson)
while mapbox's example –showing U.S.A.– works (https://www.mapbox.com/mapbox.js/assets/data/us-states.geojson).
I've triple-checked the geojson and it seems to have no errors at all, but somehow it doesn't show the polygons on the map.
Any ideas on how to solve this?
Thank you.
To test: switch on/off the comments where you see url: of the ajax call.
From your GeoJSON file:
"geometry":{"type":"Polygon","coordinates":[[[3519139.557897714,5400906.9684712365]
This GeoJSON file is in a different projection than EPSG:4326, so the coordinates are very far from valid: longitude should be >-180 and <180, latitude >-90 and <90. Reproject your data into EPSG:4326 and your example will work.

How to reproject layers (using GeoServer and OpenLayers) in order to overlay on the google maps

I am writing a code using OpenLayers. In this code, I want to display different layers in different zoom levels. Up until here, everything works. my problem began when I tried to add Google Maps as baselayers. My layers' projection system is not consistent with Google layers, so they should be reprojected. I tried to use Proj4js.transform method but it didn't work. My layers are in EPSG:3006(Sweden) and Google layers are in EPSG:900913. The following code results in a projected layer shifted to right. It means that the re-projection did not work properly.
Please let me know what is wrong with my code.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>OpenLayers map preview</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<!-- Import OL CSS, auto import does not work with our minified OL.js build -->
<link rel="stylesheet" type="text/css" href="http://gisl.nateko.lu.se:8088/geoserver/openlayers/theme/default/style.css">
<!-- add here more css definition libraries-->
<!-- Basic CSS definitions -->
<style type="text/css">
body {
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
font-size: small;
}
/* Toolbar styles */
#toolbar {
position: relative;
padding-bottom: 0.5em;
display: none;
}
/* The map and the location bar */
#map {
clear: both;
position: relative;
width: 337px;
height: 512px;
border: 2px solid black;
}
#wrapper {
width: 337px;
height: 50px;
}
#location {
float: right;
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
color: #483D8B;
background-color: white;
}
#scale {
float:left;
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
color: #483D8B;
background-color: white;
}
#nodelist{
font-family: Arial, Verdana, sans-serif;
font-size: 14px;
color: #000000;
font-style: normal;
background-color: white;
}
</style>
<!-- Import OpenLayers, reduced, wms read only version -->
<script type="text/javascript" src="http://www.openlayers.org/api/OpenLayers.js"></script>
<!-- add here more js libraries -->
<script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script>
<script src ='proj4js/lib/proj4js-combined.js'></script>
<script src ='proj4js/lib/deprecated.js'></script>
<script defer="defer" type="text/javascript">
var map;
var untiled;
var tiled;
var pureCoverage = false;
// pink tile avoidance
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 5;
// make OL compute scale according to WMS spec
OpenLayers.DOTS_PER_INCH = 25.4 / 0.28;
function init(){
format = 'image/png';
var options = {
controls: [],
projection: new OpenLayers.Projection('EPSG:900916'),
displayProjection: new OpenLayers.Projection('EPSG:4326'),
maxExtent: new OpenLayers.Bounds(
-20037508, -20037508,20037508, 20037508.34),
//modify parameter
maxResolution: 5000,
//modify parameter
//setting zoom levels
numZoomLevels:15,
units: 'm',
};
map = new OpenLayers.Map('map', options);
// setup tiled layer
var gphy = new OpenLayers.Layer.Google(
"Google Physical",
{type: google.maps.MapTypeId.TERRAIN, numZoomLevels: 15, sphericalMercator:true}
// used to be {type: G_PHYSICAL_MAP}
);
var gmap = new OpenLayers.Layer.Google(
"Google Streets", // the default
{numZoomLevels: 15, sphericalMercator:true}
// default type, no change needed here
);
var ghyb = new OpenLayers.Layer.Google(
"Google Hybrid",
{type: google.maps.MapTypeId.HYBRID, numZoomLevels: 15, sphericalMercator:true}
// used to be {type: G_HYBRID_MAP, numZoomLevels: 20}
);
var gsat = new OpenLayers.Layer.Google(
"Google Satellite",
{type: google.maps.MapTypeId.SATELLITE,
numZoomLevels: 15,
sphericalMercator:true
}
// used to be {type: G_SATELLITE_MAP, numZoomLevels: 22}
);
//add controls here
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.addControl(new OpenLayers.Control.PanZoomBar());
zf= new OpenLayers.Control.ZoomToMaxExtent({title:"Zoom to max extent"});
// create a panel to locate the zoom extent button & add the panel to the map
// use the code to create the button from ZoomToMaxExtent.js
var panel= new OpenLayers.Control.Panel({defaultControl:zf});
panel.addControls([zf]);
map.addControl(panel);
map.addControl(new OpenLayers.Control.Navigation());
map.addControl(new OpenLayers.Control.Scale($('scale')));
//end add controls
layer2 = new OpenLayers.Layer.WMS(
"Gr2LundKom:districts","http://gisl.nateko.lu.se:8080/geoserver/wms",
{
projection: map.displayProjection,
height: '600',
width: '800',
layers: 'Gr2LundKom:districts',
styles: '',
srs:'EPSG:3006',
format: format,
tiled: 'true',
transparent: 'true',
},
{
buffer: 0,
displayOutsideMaxExtent: true,
isBaseLayer: false,
reproject: true
});
Proj4js.defs["EPSG:3006"] = "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs";
Proj4js.defs["EPSG:4326"] = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
var src = new OpenLayers.Projection('EPSG:3006');
var dst = new OpenLayers.Projection('EPSG:4326');
Proj4js.transform(src, dst, layer2);
layer2.projection=dst;
layer3 = new OpenLayers.Layer.WMS(
"Gr2LundKom:public_buildings,other_buildings,roads_all,Public_Libraries",
"http://gisl.nateko.lu.se:8080/geoserver/wms",
{
projection: map.displayProjection,
height: '600',
width: '800',
layers: "Gr2LundKom:public_buildings,other_buildings,roads_all,Public_Libraries",
transparent: "true",
styles: '',
srs:'EPSG:3006',
format: format,
tiled: 'true',
transparent: 'true'
},
{
buffer: 0,
displayOutsideMaxExtent: true,
isBaseLayer: false,
reproject: true
});
Proj4js.transform(src, dst, layer3);
layer3.projection=dst;
map.addLayers([gsat,gphy,gmap,ghyb,layer2]);
//map.setCenter(new OpenLayers.LonLat(1335967.698, 6179172.362), 22);
map.zoomToExtent(new OpenLayers.Bounds(
-20037508, -20037508,20037508, 20037508.34));
// change the dislapy layers with the chandge of scale
map.events.register('zoomend', this, function (event) {
var zLevel = map.getZoom();
if( zLevel == 1 || zLevel == 2 || zLevel == 3 )
{
layer3.setVisibility(false);
layer2.setVisibility(true);
}
if( zLevel == 4 || zLevel == 5 || zLevel == 6)
{
layer2.setVisibility(false);
layer3.setVisibility(true);
map.addLayers([gsat,gphy,gmap,ghyb,layer3]);
}
});
}
</script>
</head>
<body onload="init()">
Map viewer using Geoserver and MapLayers
<br><br>
<div id="map">
</div>
<br>
<div id="wrapper">
<div id="location">location</div>
<br>
<div id="scale">
</div>
</div>
<br>
<div id="nodelist" >
--> Click on the map to get feature info
</div>
</body>
Well, I know it is a workaround, but I see you use geoserver, so you could convert your layers in geoserver into google mercator (you should use the code EPSG:3857, as I recall EPSG:900916 didn't work for me). I struggled with this problem too, and that was the only thing which helped me.
This problem comes however only if you use wms, wfs layers you could transform easily.
And also I think that you should not try to visualize everything in EPSG:4326 but in google mercator instead.
I hope this helps.
I think you have a typo here, it should be EPSG:900913 instead of EPSG:900916, because it's the representation of google with numbers (900913)

Categories

Resources