I am very new to working with openlayers. The tutorial below teaches how to show a map and build local, but the problem is I can not change the center of the map. Even If I change the location, it shows aways the "zero" point of the map.
https://openlayers.org/en/latest/doc/tutorials/bundle.html
below are the .js example and .html, the problem is the center: I can't change the map center
import 'ol/ol.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
const map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
center: [0, 0],
zoom: 0
})
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Using Parcel with OpenLayers</title>
<style>
#map {
width: 400px;
height: 250px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="./index.js"></script>
</body>
</html>
Every GIS map has a coordinate system. GIS web applications are very similar to desktop GIS maps, so they have a coordinate system too. in OpenLayers known as projection.
In OpenLayers, every web app made up of a Map() class that needs a view() to show the map. By default, every view() use Web Mercator projection or EPSG:3857 as its projection. so in your code, you should put the center in EPSG:3857 coordinate system. If you want to use center coordinate in WGS 84 or lat-long numbers you should change the view projection to EPSG:4326 like this:
view: new ol.View({
center: [0,0],
projection: 'EPSG:4326',
zoom: 0
})
Projection is really important for further usages. If you have some data in a specific projection, Openlayers can't display them on a map with another projection. for example, if you have some data in WGS 84 you can't use them on the default view(cause it's Web Mercator).
So before choosing the view projection read about the limits. e.g. Basemaps are not available in every projection just like normal layers.
Also, there is another option you can use. Projecting the whole layer on the fly(in client browser) needs a massive process but we always can project a point or a single feature and use them among our layers or base map. In your case, you can only project your center point and use the map in Web Mercator. for this option, you need to use fromLonLat() like this:
center: ol.proj.fromLonLat([0,0])
Hope to be clear.
Try this one for your center:
center: ol.proj.fromLonLat([longitude,latitude])
Related
I aim to overlay a tile layer on top of another. The first tile layer is created using L.tileLayer() using the url: baseUrl='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' and the second tile layer is created using a wms service (L.tileLayer.wms) hosted on geoserver which is serving some .tif images as tiles. I want to create something like: https://alpha.anthropo.co/znz-demo
As can be seen in the demo, once the user zooms out one can see the base map and after a specific zoom level, the .tif images can also be seen on top of the base map.
In my implementation, I can only see either one tile layer or another. And after a certain zoom level, I can see the geoserver tile layer but cannot see the osm layer at all and I suppose that it might be because the osm tilelayer might not be supporting zoom levels that high and hence I am only seeing the geoserver tile layer.
I have tried creating/setting pane levels, making the served tiles transparent using geoserver, layer groups, setting transparent param to true and format param to 'image/png' at the same time when creating the tilelayer, and using the layer.bringToFront() method but none of these seem to help in this case or maybe they do but because I am a newbie to leaflet/web mapping world I am not using them the right way.
geoserver footprint behaviour and merge behaviour configuration screenshot
It would be great if you can help me with this :) Thanks...!
My code is as follows:
<!DOCTYPE html>
<html>
<head>
<!-- Title -->
<title> Sample: Loading tiles from Geoserver </title>
<!-- Including Leaflet CSS file in the head section of the document. -->
<link rel="stylesheet" href="./leaflet_js/leaflet.css" />
<link rel="stylesheet" href="./style.css" />
<!-- Including Leaflet JavaScript file after Leaflet's CSS file. -->
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="./leaflet_js/leaflet.js"></script>
</head>
<body>
<div id="map"></div>
<script>
// Latitude and Longitude of the point that is displayed when the map first loads.
var startPoint = [latitude=-5.733, longitude=39.298]
// Creating map options
var mapOptions = {
center: startPoint,
zoom: 15,
crs: L.CRS.EPSG3857,
};
// Creating a map object
var map = L.map('map', mapOptions);
var tanzania_layer = L.tileLayer.wms(
baseUrl='http://localhost:8080/geoserver/OpenAI_Tanzania/wms?', {
layers: 'train',
maxZoom: 25,
crs: L.CRS.EPSG3857,
noWrap: true,
tranparent: true,
format: 'image/png'
});
var osm_layer = L.tileLayer(
baseUrl='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 25,
attribution: '© OpenStreetMap',
crs: L.CRS.EPSG3857,
noWrap: true,
tranparent: true,
format: 'image/png'
});
baseLayer = L.layerGroup([tanzania_layer, osm_layer]);
map.addLayer(baseLayer);
</script>
</body>
</html>
My output
I have taken care of the crs and if I only show the geoserver tile layer then I can see the data here so the layers align as well.
I would like to see the geoserver tile layer data on top of the current osm layer that is shown in the output screenshot.
Thanks again :)
I'm trying to display the MART transit system on a web map I'm building with the Javascript API. It's listed here by Google as one of the cities that they have transit data for, and indeed when you go to Google Maps there is bus data there.
The transit layer example page listed here works and displays transit data for Boston, Chicago, DC, etc, but not MART. Code as follows:
<body>
<div id="map"></div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {lat: 42.54, lng: -71.79}
});
var transitLayer = new google.maps.TransitLayer();
transitLayer.setMap(map);
var bikeLayer = new google.maps.BicyclingLayer();
bikeLayer.setMap(map);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyChFsvLbqcDVBUQMFQJaMxA19PhTys6ZxY&callback=initMap">
</script>
</body>
Seems like it should work but no luck. The map appears, centered in the correct location, but no transit data for MART. If you go look at Boston, however, the transit layer appears there (as well as DC, Chicago, etc). In general it seems to be displaying train lines only but no bus lines. Any help would be greatly appreciated. Thanks!
You might to add some css because it's working but not showing
<style>
#map {
height: 400px;
width: 100%;
}
</style>
Here's a link to my working version
https://jsfiddle.net/mpuzz0tb/6/
If you want to show a map for both transit and bicycles, You need two seperate ids for the maps to be displayed - #dalewatt
I'm using Leafletjs with D3 to show a map.
I only want to show the UK in the map.
Is it possible with Leaflet and D3 to only show the UK.
It is certainly possible.
Now the solution depends whether you want to use D3 to draw the UK, or you want to get it from a Tile Server.
In the latter case, there is a more recent solution than the one proposed in the link in xmojmr's comment.
See Prevent tiles outside of polygon from loading
The idea is to use the TileLayer.BoundaryCanvas plugin, which you can specify a GeoJSON boundary option to hide everything that is not within that GeoJSON geometry.
BoundaryCanvas is a plugin for Leaflet mapping library to draw tiled raster layers with arbitrary boundary. HTML5 Canvas is used for rendering.
Live demo with a rough UK shape:
var map = L.map("map");
$.getJSON('https://cdn.rawgit.com/johan/world.geo.json/34c96bba/countries/GBR.geo.json').then(function(geoJSON) {
var osm = new L.TileLayer.BoundaryCanvas("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
boundary: geoJSON,
attribution: '© OpenStreetMap contributors, UK shape johan/word.geo.json'
});
map.addLayer(osm);
var ukLayer = L.geoJSON(geoJSON);
map.fitBounds(ukLayer.getBounds());
});
#map {
height: 500px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.2.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.2.0/dist/leaflet-src.js"></script>
<script src="https://cdn.rawgit.com/aparshin/leaflet-boundary-canvas/f00b4d35/src/BoundaryCanvas.js"></script>
<div id="map"></div>
I'm using AngularJS, Leaflet, and Angular-leaflet-directive in the following example which I got from the Angular-leaflet-directive project. This example works when using public tile servers, including the public ArcGIS server the example is currently pointing to.
According to several online sources of documentation, including these two from open street maps and mapbox, the number of tiles available at a particular zoom level should be 2^z X 2^z, where z is the zoom level. So, at zoom level 0 we should get 1 tile, at 1 we should get 4 tiles, and so on.
The issue I have only occurs when pointing to a privately hosted (corporate intranet) ESRI ArcGIS tile server. When I try to view the page below as is, but with the private tile server's url instead of the http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}, I only see partial maps at zoom level 0 and 1.
After poking around a little bit I realized that the tile server wants to send two tile instead of 1 at zoom level 0, 6 tiles instead of 4 at zoom level 1. And the problem continues at deeper zoom levels. When looking at the urls for the individual tiles (for example ../0/0/0 and ../0/0/1 at zoom level 0), I see that we do get the composite map we expect if we put together remaining tiles which are available at that zoom level. Meaning if leaflet wanted to build the entire map the information is available.
I am very new to Leaflet and Maps in general, but I feel that by telling leaflet to expect more tiles at a given zoom level, it should be able to get the complete picture, but after searching leaflet documentation, I was unable to find such a configuration.
My questions: is there such a setting? If so what is it? Maybe the question is missing something or I don't know enough to ask the right question. Am I looking at the right documentation? Any guidance would be appreciated.
<html>
<head>
<title>A Leaflet map!</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
#map{ width: 900px; height: 500px; }
</style>
</head>
<body>
<div id="map"></div>
<script>
// initialize the map
var map = L.map('map').setView([42.35, -71.08], 13);
// load a tile layer
L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}',
{
maxZoom: 17,
minZoom: 9
}).addTo(map);
</script>
</body>
</html>
Maybe the question is missing something or I don't know enough to ask the right question.
I think you're missing the concept of map projections. If a map is using EPSG:3857, then chances are that the zoom 0 is covered by 1 tile. If it's in EPSG:4326, then it's 2 tiles.
Compare these (static) images from leaflet maps of NASA's Blue Marble:
Both are correct, but they use different projections (EPSG:3857 on top and EPSG:4326 on bottom).
I strongly suggest you research what projection your tiles are using. You might need a bit of extra research on map projections and even Proj4Leaflet to get it working, but at least you know ehre to look.
Here is my solution based on comments from #IvanSanchez. Note that I'm pointing to a public server that serves up EPSG:4326 and adding crs:L.CRS.EPSG4326 to defaults. One important point to note is that this is not fully supported by the current stable version of leaflet (0.7.7). In order to get it to work, I upgraded to 1.0.0 Beta2. For more information on this issue, including alternative to using the beta version, see https://github.com/Leaflet/Leaflet/issues/1207.
<!DOCTYPE html>
<html ng-app="demoapp">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="lib/angular-1.4.2/angular.min.js"></script>
<script src="lib/leaflet/dist/leaflet.js"></script>
<script src="lib/angular-leaflet-directive-master/dist/angular-leaflet-directive.min.js"></script>
<link rel="stylesheet" href="lib/leaflet/leaflet.css" />
<script>
var app = angular.module("demoapp", ["leaflet-directive"]);
app.controller('BasicCustomParametersController', [ '$scope', function($scope) {
angular.extend($scope, {
london: {
lat: 51.505,
lng: -0.09,
zoom: 1,
noWrap: false,
minZoom: 1,
maxZoom: 10
},
defaults: {
//EPSG:3857
// tileLayer: "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}",
//EPSG:4326
tileLayer: "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/tile/{z}/{y}/{x}",
zoomControlPosition: 'topright',
tileLayerOptions: {
opacity: 0.9,
detectRetina: true,
reuseTiles: true,
},
scrollWheelZoom: false,
//use EPSG4326. Not fully supported in leaflet 0.7.7. Works with 1.0.0 Beta2
crs:L.CRS.EPSG4326
}
});
}]);
</script>
</head>
<body ng-controller="BasicCustomParametersController">
<leaflet lf-center="london" defaults="defaults" width="100%" height="480px"></leaflet>
<h1>Using custom default parameters</h1>
</body>
</html>
In this AngularJS SPA using NgMap, I have map pins being set on data filtering. On initial load of the map, the map is centered on some place out in the ocean, not the coordinates I have set in the map object in the center parameter. I've also tried setting this on the map initialization without any success.
$scope.$on('mapInitialized', function(event, map) {
var myLatlng = new google.maps.LatLng(43.6650000, -79);
var mapOptions = {
draggable: true,
zoom: 4,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
});
<map zoom="3" center="[43.6650000,-79]" scrollwheel="false" zoom-to-include-markers="true">
<marker ng-repeat="site in filteredPins track by $index" position="[{{site.Latitude}},{{site.Longitude}}]" id="{{site.Id}}" title="{{site.SiteName}}"></marker>
</map>
Where/how does one set the initial map location on load if not through the <map> center param, or the center option in the map options when the map is initialized?
Plunkr: http://plnkr.co/edit/u75fJT?p=preview
Your code is correct, the initial map center is exactly at the coordinates you've specified, the problem seems to be on the html zoom-to-include-markers="true" that is changing the map center after loaded
<map zoom="3" center="[43.6650000,-79]" scrollwheel="false" zoom-to-include-markers="true">
remove zoom-to-include-markers="true" and it will work
It seems the latitude and longitude you provided is in ocean. I have tried it also and show me in ocean. :).
Just change the latitude and longitude to the correct location, just note, zoom-to-include-markers="true" working well in mine, it doesn't cause the map to display the coordinate in ocean.
I had this problem because the map init occurred when the value bound to center was [0,0]. when the actual center was populated into the controller, the map was not visible so it didnt re-center.
the way i solved it was by doing an explicit $scope.$digest when I made the map visible