How to display ESRI Vector base map in Openlayers 3 - javascript

I am trying to add the new ESRI Vector Basemaps in OpenLayers 3. I have gotten so far as to display the layer un-styled by modifying the Mapbox Example published by OpenLayers.
Clearly I had to remove the style: createMapboxStreetsV6Style() option to get the esri layer to display. So basically the map does not know the style information to display the layer correctly.
I think it should be possible to do it because ESRI's Leaflet port and example is doing this already. I think information on esri's style IDs is available in here Leaflet code.
OpenLayers should already be able to use all this information as it is able to display Mapbox Layer. What I need help with is, how to make it use ESRI's style information.
Here's what I have so far (codepen here):
var map = new ol.Map({
layers: [
new ol.layer.VectorTile({
source: new ol.source.VectorTile({
format: new ol.format.MVT(),
tileGrid: ol.tilegrid.createXYZ({maxZoom: 22}),
tilePixelRatio: 16,
url: 'https://basemaps.arcgis.com/v1/arcgis/rest/services/World_Basemap/VectorTileServer/tile/{z}/{y}/{x}.pbf'
})
})
],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
.map {
background: #f8f4f0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.1.0/ol.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.1.0/ol.css" rel="stylesheet"/>
<div id="map" class="map"></div>

There is a separate library, https://npmjs.com/package/ol-mapbox-style, which makes it easy to consume vector tile maps including their styles in OpenLayers. It reads the style doc and builds the whole map from it. For one of the ESRI maps you linked above, the code to get that map in OpenLayers would be
var map = new ol.Map({
target: 'map'
});
olms.apply(map, 'https://www.arcgis.com/sharing/rest/content/items/4f4843d99c34436f82920932317893ae/resources/styles/root.json?f=json');
You can replace 4f4843d99c34436f82920932317893ae with one of the other map ids listed in the Leaflet example to get the other maps.
You can also play with that code - I have created a CodePen: https://codepen.io/ahocevar/pen/xLaBVV.

#ahocevar's suggest is perfect,
esri's root.json, sprite and glyphs are not full URL, the are only last part as see below
In your example, those not full URL works, but, I have test it in mapbox js api, it failed, error is can't parse URL,
I have to change those url to a full URL, to make it works.
root_json = {
"version" : 8,
"name": "test",
//"sprite" : original_rootJson.sprite, // original is not a full URL, not work "../sprites/sprite"
// "sprite" : "https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/2020_USA_Median_Age/VectorTileServer/resources/sprites/sprite",
"sprite" : _sprite,
// "glyphs" : original_rootJson.glyphs, // original is not a full URL, not work "../fonts/{fontstack}/{range}.pbf"
// "glyphs" : "https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/2020_USA_Median_Age/VectorTileServer/resources/fonts/{fontstack}/{range}.pbf",
"glyphs" : _glyphs,
// root json specification : https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/
"sources" : {
"esri" : {
"type" : "vector",
// By supplying TileJSON properties such as "tiles", "minzoom", and "maxzoom" directly in the source:
"tiles": [
// "https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/2020_USA_Median_Age/VectorTileServer/tile/{z}/{y}/{x}.pbf"
_tile_pbf
],
// "maxzoom": 14
// By providing a "url" to a TileJSON resource
// not work,yet
// "url" : "https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Esri_Childrens_Map/VectorTileServer/tile/{z}/{y}/{x}.pbf"
// "url": "http://api.example.com/tilejson.json"
}
},
"layers": original_rootJson.layers
} // root_json

Related

OpenLayers GeoJSON Layer projection not working

Using the code below, I've been unable to get my single GeoJSON point feature to appear on the map. Or possibly if it does appear on the map in the correct location. It appears in Germany, whereas it should appear in Tasmania, Australia. Same location it appears at if I provide no projection at all. Therefore it seems that there is some problem with the way I'm setting the projection.
I have a feeling that I'm using defaultDataProjection and/or featureProjection incorrectly, but I find the documentation to be fairly unclear on how these should be used.
The same projection works on my other (non-GeoJSON) layers OK.
How can I correct my code to get this to work?
var geojsonObject = {"type":"FeatureCollection","features":[{"geometry":{"type":"Point","coordinates":[503619.026899999939,5420925.347199999727]},"properties":{"label":{}},"type":"Feature"}]};
proj4.defs('layerProj', '+proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ')
var vectorSource = new ol.source.Vector({
features: (new ol.format.GeoJSON({
defaultDataProjection: 'layerProj',
}).readFeatures(geojsonObject, { featureProjection: 'layerProj' }))
})
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({image: new ol.style.Circle({fill: new ol.style.Fill({color: '#8888FF'}), radius: 10, points: 0})}),
});
map.addLayer(vectorLayer);
Your format: should be features: Also defaultDataProjection in the GeoJSON options in OpenLayers 4 changes to dataProjection in later version, so it may be better to specify dataProjection in the readFeatures options where the name is the same in all versions. featureProjection should always be set to the view projection
features: new ol.format.GeoJSON().readFeatures(geojsonObject, {
dataProjection: 'layerProj',
featureProjection: map.getView().getProjection()
})
If you are using OpenLayers 5 or above you will also need to register proj4 after the layerproj definition
ol.proj.proj4.register(proj4);

How can I load a country specific map into OpenStreetMap?

I want to load a country specific map (say https://openstreetmap.in). I'm using the following code snippet, but it loads the map from https://www.openstreetmap.org:
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
]
Can anybody please tell me how I can load a country specific map?
You need to create a custom tile layer, either a so-called OSM layer or a XYZ layer. The OpenLayer examples Localized OpenStreetMap and XYZ explain how to specify a custom tile source.
The tile server URL for openstreetmap.in is https://{a-c}.tiles.mapbox.com/v4/openstreetmap.1b68f018/{z}/{x}/{y}#2x.png?access_token=pk.eyJ1IjoiamluYWxmb2ZsaWEiLCJhIjoiY2psejFtZG8wMWhnMjNwcGFqdTNjaGF2MCJ9.ZQVAZAw8Xtg4H2YSuG4PlA.
Your code should then look roughly like this:
var osmIndia = new TileLayer({
source: new OSM({
attributions: [
'© mapbox and OpenStreetMap'
],
url: 'https://{a-c}.tiles.mapbox.com/v4/openstreetmap.1b68f018/{z}/{x}/{y}#2x.png?access_token=pk.eyJ1IjoiamluYWxmb2ZsaWEiLCJhIjoiY2psejFtZG8wMWhnMjNwcGFqdTNjaGF2MCJ9.ZQVAZAw8Xtg4H2YSuG4PlA'
})
});
[...]
layers: [
osmIndia
]

Adding a Shapes files as a Layer on Mapbox Map

I have a shapes file from here. I wish to add it on a Map, similar to what is done on the web page. I am not quite sure how to proceed with it. I want to use it on Web and hence use JavaScript.
Someone suggested me to use the shapes file as a Layer on the map. But how to go about it? Anyone experience with Mapbox, Leaflet or OSM please guide.
I was finally able to add the shapes file by uploading it as a tileset to Mapbox Studio.
It provided me with a map Id and source-layer name which I was able to add as a Layer on my Mapbox map as follows:
map.addLayer({
id: '<id>',
type: 'fill',
source: {
type: 'vector',
url: 'mapbox://<map-id>' // Mapbox tileset Map ID
},
'source-layer': '<layer-name>', // name of tilesets
'paint': {
'fill-color': '#088',
'fill-opacity': 0.8,
'fill-outline-color': '#000'
}
});
In order to load a SHP file and display it on a Leaflet / Mapbox.js map, you have several Leaflet plugins that can make the task easy.
For example leaflet.shapefile (online demo where you can drop your zipped SHP and DBF files).
The data source that you mention also provides KML format, which may be easier to use.
For KML, you can use for example leaflet-omnivore:
universal format parser for Leaflet & Mapbox.js
var map = L.mapbox.map('map', 'mapbox.streets')
.setView([38, -102.0], 5);
omnivore.kml('a.kml').addTo(map);
Live example with Leaflet and leaflet-omnivore: https://plnkr.co/edit/KVXqBScBuIrAahg4VsGi?p=preview

loading GeoJSON markers into MapBox

I'm trying to figure out how to load GeoJSON list on lon/lat coordinates into a MapBox map. I think I'm close, I just can't seem to get it actually working.
I have a demo page set up here: http://sandbox.charliehield.com/mapbox/
Here's the GeoJSON file:
{
"type": "MultiPoint",
"coordinates": [
[
"-105.277803",
"40.006977"
],
[
"-93.304988",
"44.947198"
],
[
"151.206990",
"-33.867487"
]
]
}
The HTML is simply:
<div id="map"></div>
And the JS:
var map = mapbox.map('map');
map.addLayer(mapbox.layer().id('examples.map-zr0njcqy'));
map.ui.zoomer.add();
// example.geojson is a well-formed GeoJSON document. For this
// style, the file must be on the same domain name as the map,
// or loading will not work due to cross-domain request restrictions
var markers = mapbox.markers.layer().url('markers.geojson');
mapbox.markers.interaction(markers);
map.addLayer(markers);
// Zoom and center the map
map.zoom(2).center({ lat: 39.74739, lon: -105 });
Looks like you need to format your geojson a little more explicitly with a geometry object and key value pairings. See http://mapbox.com/mapbox.js/example/custom-marker-tooltip as an example.
I had the same issue loading geojson to my mapbox map. The comments in the JS actually pointed out the reason: there are cross-domain request restrictions.
You could check the same origin policy and you would want to run the application somewhere else.

How to bound tile layers in Bing Maps AJAX Control, Version 7.0

I have been attempting to overlay tiles from Weather Central onto a Bing map but have been encountering a problem. I am able to call upon a tile and push it onto the map, however, no matter how big the tile is, it puts the tile everywhere on the map. I would like to be able bound it to a specific place but cannot figure out how in 7.0. In 6.3 the specifications seem straightforward : http://msdn.microsoft.com/en-us/library/bb429629.aspx but not in 7.0. They have an example here: http://www.bingmapsportal.com/isdk/ajaxv7#TileLayers1 but even using their code it will still put the tiles everywhere.
Here is my code so far:
function GetMap() {
map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), { credentials: "my creds" });
var tileSource = new Microsoft.Maps.TileSource({ uriConstructor:
'http://datacloud.wxc.com/?type=tile&datatype=forecast&var=Temperature&time=now&bing=023212&vs=0.9&passkey=my_passkey', height: 256, width: 256});
var tilelayer = new Microsoft.Maps.TileLayer({ mercator: tileSource, opacity: .7 });
// Push the tile layer to the map
map.entities.push(tilelayer);
}
Where I do the function GetMap() onload.
Thanks
It looks like you're hardcoding a particular tile quadkey (023212) in your request - you need to replace this with the {quadkey} placeholder to request the appropriate tile image for each location. i.e.:
map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), { credentials: "my creds" });
var tileSource = new Microsoft.Maps.TileSource({ uriConstructor:
'http://datacloud.wxc.com/?type=tile&datatype=forecast&var=Temperature&time=now&bing={quadkey}&vs=0.9&passkey=my_passkey', height: 256, width: 256});
var tilelayer = new Microsoft.Maps.TileLayer({ mercator: tileSource, opacity: .7 });
// Push the tile layer to the map
map.entities.push(tilelayer);
(untested, since I don't have a passkey to access the service in question)

Categories

Resources