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
Related
I need a direction, 'cause I don't know how to look for it, or basically how to do that.
Every time a user presses a locate button it will locate his position (already done this part)
And then, I want to give certain details about his city (in my case, I want to give corona details of people amount that are infected in the city area)
for example: so lets say the user lives in new york, and then he clicks on locate position, it gives him the amount of sick people in his area.
i used this website for my code:
https://developers.arcgis.com/javascript/3/jssamples/widget_locate.html
my code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>OpenStreetMap</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.35/esri/css/esri.css">
<style>
html, body, #esri-map-container {
padding: 0px;
margin: 0px;
height: 100%;
width: 800px;
height: 500px;
}
#LocateButton {
position: absolute;
top: 95px;
left: 20px;
z-index: 50;
}
</style>
<script src="https://js.arcgis.com/3.35/"></script>
<script>
var map;
require([
"esri/map",
"esri/dijit/LocateButton",
"dojo/domReady!"
], function(Map, LocateButton)
{
map = new Map("map", {
center: [-56.049, 38.485],
zoom: 3,
basemap: "streets"
});
geoLocate = new LocateButton({
map: map
}, "LocateButton");
geoLocate.startup();
});
</script>
</head>
<body>
<div id="map" class="map">
<div id="LocateButton"></div>
</body>
</html>
So yeah, I don't know where to search really, if you can direct me or help me out figuring how am I supposed to do that.
You can get some information data about the location detected by using the 'locate' event.
In there you will find the coordinates of the location and much more. I personally tried to convert coordinates to address but there is not much ArcGIS support right now. If you find a way through Google's API maybe you will be able to finally get the city through the coordinates ArcGIS gives you.
geoLocate.on('locate', (data) => {
console.log(data);
});
You will find a working example of the event I mentioned above here.
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.
The code I have so far is using the Google Maps API to take in something the user enters, looks it up on the map, and then appends search they entered to the right of the map. The one part I am missing is that for the searches on the right, I have to make them be able to be clicked and upon click they go to the marker on the map. I was wondering if anyone had any advice or hints to help me figure it out, since I have tried a lot of different things (for some reason using the .on('click',...) wouldn't work properly).
Thank you!
.html file:
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script src = "project2.js"></script>
<link rel = "stylesheet" type = "text/css" href = "project2.css">
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
</head>
<body>
<form>
<div>
<label> Address: </label>
<input id = "address" type = "text">
<input id = "submit" type = "button" value = "Add">
<br><br>
</div>
</form>
<section>
<ul>
</ul>
</section>
<div id="map"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAGysAFeYIRV2qqMeEcnehH9igIaSYxvvs&callback=initMap"></script>
</body>
</html>
.js file:
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 41.083, lng: -74.174},
zoom: 8
});
var geocoder = new google.maps.Geocoder();
document.getElementById('submit').addEventListener('click', function() {
showAddress(geocoder, map);
//getLinks();
});
}
function showAddress(geocoder, newMap)
{
var address = document.getElementById('address').value;
//console.log(address);
$('<li/>').addClass('list').text(address).appendTo('ul');
geocoder.geocode({'address': address}, function(results, status) {
if (status === 'OK') {
newMap.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map:newMap,
position: results[0].geometry.location
});
}
else {
alert('Geocode was not successful for reason: ' + status);
}
});
}
/*
function getLinks()
{
console.log("hey");
$('#elements').on('click', 'li', function(){
alert($(this).text());
console.log("hey2");
});
}*/
.css file:
input[type = text]
{
width: 375px;
}
li {
list-style-type: none;
width: 450px;
border-style: solid;
padding: 0.3em;
margin-left: 475px;
margin-right: auto;
margin-bottom: .5em;
}
.list {
background-color: #8E8989;
}
#map {
position:absolute;
top: 50px;
height:60%;
width:40%;
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
}
html, body{
height: 100%;
margin:0;
padding:5px;
}
Thank you!
I would suggest adding an id to the <ul>, and attach a click event listener to it instead of the dynamically created <li>.
For example:
<ul id="address-list">
Then in javascript, use:
$("#address-list").on("click",".list",function(){
/* Do something */
})
To add event on dynamically generated elements you need to use something like
$('body').on('click', 'li', function() { // do something });
I want to display a polyline underground in cesium.js. But I have no idea about this.
It seems that cesium has not provided official underground function for the reason that cesium cameral can not be placed undergroud,but the underground effect can be gained by an alternative way--translucent terrain.
According How to display underground entity? in Cesium-dev google group,I have achieved a barely satisfactory approach to showing the entity(including gltf models) underground.The displaying effect is as what the GIF file shows.This appoach contains mainly 3 steps.
For gif, see here.
1.change only one line code in cesium source code;get the cesium source code,then find the file named GlobeSurfaceTileProvider.js,change
command.pass = Pass.GLOBE;
to
command.pass = Pass.TRANSLUCENT;
2.generate the cesium release code with gulp tool;use your CLI to execute gulp release. PS: You may need set your node environment and install the dependency node modules and install gulp tool.
3.Implemention code.PS: note the following snippet can run only if you have changed the cesium source code which is illustrated in step one.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8">
<!-- Tell IE to use the latest, best version. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Hello World!</title>
<script src="../Build/Cesium/Cesium.js"></script>
<style>
#import url(../Build/Cesium/Widgets/widgets.css);
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
position: relative;
}
.tools {
position: absolute;
top: 20px;
left: 20px;
width: 100px;
}
</style>
</head>
<body>
<div class="container">
<div id="cesiumContainer">
</div>
<div class="tools">
Opacity: <input id="btnImageryAlpha" type="range" min="0" max="10" value="10" oninput="change()" />
</div>
</div>
<script>
function change() {
var value = document.getElementById("btnImageryAlpha").value;
if (viewer.imageryLayers) {
for (var i = 0; i < viewer.imageryLayers.length; i++) {
viewer.imageryLayers.get(i).alpha = value / 10;
}
}
console.log(value);
}
var terrainProvider = new Cesium.CesiumTerrainProvider({
url: 'https://assets.agi.com/stk-terrain/v1/tilesets/world/tiles',
requestVertexNormals: true
});
var viewer = new Cesium.Viewer('cesiumContainer', {
//skyAtmosphere: false,
//orderIndependentTranslucency: false,
baseLayerPicker: false,
terrainProvider: terrainProvider
});
//viewer.scene.globe.depthTestAgainstTerrain = false;
//change the ugly blue color to black
viewer.scene.globe.baseColor = new Cesium.Color(0, 0, 0, 0);
//default is 1
//viewer.scene.globe.imageryLayers.get(0).alpha = 0.5;
var blueBox = viewer.entities.add({
name: 'Blue box',
position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 5),
box: {
dimensions: new Cesium.Cartesian3(400000.0, 300000.0, 500000.0),
material: Cesium.Color.BLUE
}
});
viewer.zoomTo(blueBox);
</script>
</body>
</html>
Yes, this is supported in cesium. It can be hard to see sometimes since the camera cannot go bellow the ellipsoid.
var viewer = new Cesium.Viewer('cesiumContainer');
var purpleArrow = viewer.entities.add({
name : 'Purple straight arrow at height',
polyline : {
positions : Cesium.Cartesian3.fromDegreesArrayHeights([-75, 43, -200000,
-90, 43, -200000]),
width : 10,
followSurface : false,
material : new Cesium.PolylineArrowMaterialProperty(Cesium.Color.PURPLE)
}
});
viewer.zoomTo(viewer.entities);
Live
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)