PDF as a map in Leaflet JS? - javascript

I'm wondering if it's possible to upload a PDF document to use as a map in Leaflet, or if it needs to be converted to another format first? I've only seen examples that actually reference a map like this:
// initialize the map
var map = L.map('map').setView([42.35, -71.08], 13);
// base map
L.tileLayer('http://tiles.mapc.org/basemap/{z}/{x}/{y}.png',
{
attribution: 'Tiles by MAPC, Data by MassGIS',
maxZoom: 17,
minZoom: 9
}).addTo(map);
// bike lanes
L.tileLayer('http://tiles.mapc.org/trailmap-onroad/{z}/{x}/{y}.png',
{
maxZoom: 17,
minZoom: 9
}).addTo(map);
Docs: http://leafletjs.com/reference-1.3.0.html

TL;DR: No.
PDFs are complex to view - they are not one simple HTML element. This is because there is no "one true view" of a PDF. Do you want to display one page, multiple pages, the table of contents as text, one image of one specific page? Without knowing that, it's not possible to have a one-PDF-file-to-one-HTML-element mapping. Which means there's no way to tell Leaflet what to display.
In theory, one could leverage pdf.js to parse the PDF file, select some specific content, and then spawn some HTML elements as appropriate. However, the cost of doing so far exceeds the cost of exporting the data to some other format better suited for GIS work.

Related

Which is base layer out of two tile layers

I can't find docs about it, consider:
// base map
L.tileLayer('http://tiles.mapc.org/basemap/{z}/{x}/{y}.png',
{
attribution: 'Tiles by MAPC,
Data by MassGIS',
maxZoom: 17,
minZoom: 9
}).addTo(map);
// bike lanes
L.tileLayer('http://tiles.mapc.org/trailmap-onroad/{z}/{x}/{y}.png',
{
maxZoom: 17,
minZoom: 9
}).addTo(map);
So we added two tile layers to the map right? But which of the above two is set as a base layer now?
Can a map have multiple base layers at once? (because I read somewhere base layers normally should be mutually exclusive).
Extra: Can I change a base layer without using the layer control mechanism? (e.g. only programatically).
So we added two tile layers to the map right? But which of the above
two is set as a base layer now? Can a map have multiple base layers at
once? (because I read somewhere base layers normally should be
mutually exclusive).
Yes they are mutually exclusive in display so that means you can display only one layer at a time. It's not documented but the last layer added will become the base layer which is being displayed.
Extra: Can I change a base layer without using the layer control
mechanism? (e.g. only programatically).
Yes you can using addLayer/removeLayer method.
map.removeLayer(base map layer name here);
map.addLayer(bike lane layer name here);
So we added two tile layers to the map right?
Yes.
But which of the above two is set as a base layer now?
Leaflet has no concept of base layer, so the answer is "none".
Can a map have multiple base layers at once? (because I read somewhere base layers normally should be mutually exclusive).
Depends on what you consider to be a "base layer".
I can, for example, have a map with several sets of opaque tiles, each of them being able to function as a base layer of a map, and make one of them semitransparent.
Usually, map frameworks assume that a tilelayer (or one tilelayer in a set of tilelayers) can be the basic information for your map, and in those circumstances, such set of tilelayers should be exclusive. Hence the wording of L.Control.Layers.
Leaflet does not constrain you to have a fully-opaque exclusive L.TileLayer. You can even have a Leaflet map without a single L.TileLayer. And of course, you can control visibility of your layers with map.removeLayer(lyr), map.addLayer(lyt), layer.addTo(map) and layer.remove(). Ultimately, the logic to control layer exclusivity (and opacity) is up to you.

Custom Overlays in OpenLayers 3

Currently I am working on Openlayers 3.
I used custom overlays in Google maps Javascript api v3 to add customized markers as html div on the map. And these markers are grouped and plotted in different custom overlays.
Now I am trying to implement the same in OpenLayers 3, but I couldn't find any solution as the overlays in OpenLayers 3 takes one marker in one overlay.
Can I group overlays in OpenLayers 3 in order to group the markers? Or Is there any other options available?
You have multiple possible options.
A) If you have only one dataset, then you could use a StyleFunction. See this ol3 vector example, more specifically this section of code:
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'https://openlayers.org/en/v3.20.1/examples/data/geojson/countries.geojson',
format: new ol.format.GeoJSON()
}),
style: function(feature, resolution) {
style.getText().setText(resolution < 5000 ? feature.get('name') : '');
return style;
}
});
See the style property? It can be a ol.style.Style or a style function, like demonstrated above. The function receives the feature and current resolution of the map view as argument and is called every time the feature gets rendered (or re-rendered). Returning a ol.style.Style or array of style objects will render the feature using the/these styles.
The feature can have unique properties, i.e. feature.getProperties(). Using as many properties within the feature(s), you can return a unique array of unique style objects.
Here's a more complex ol3 example featuring style functions that you can look and have an example of dynamic styling depending on the resolution. That could give you a better idea of what you could do with the feature properties.
B) If you have multiple datasets, then you can create one vector layer per dataset and define a unique style object on the layer, which would render the features all the same.

Setting the selected layer on a Leaflet/Mapbox L.Control.Layers

I have a map with a few base layers. Users can choose the base layer and then save the map. After saving the map, the system loads it with the new base layer. That base layer should be selected in the L.Control.Layers control. However, there's no way in the API to select a base layer.
Anyone knows a way around this, or a different plug in?
UPDATE: Here is the code I use. MapConfigs has the ids in MapBox, and can create the map that L.control.layers requires.
var map = L.mapbox.map( components.mapDivId , MapConfigs.idFor(baseLayerName) );
map.addControl( L.control.layers(
MapConfigs.toBaseLayersControlMap(map)
).setPosition("topright"));
Thanks!
Why not store references to all the base layers available in a hash, then use addLayer or removeLayer (http://leafletjs.com/reference.html#map-addlayer) as needed to programmatically select base layers?. Something like below.
var tileLayers = {light: L.tileLayer('lightUrl'),dark: L.tileLayer('darkUrl')}

How to make a google map not to leave world bounds?

I wonder how to make a google map not to leave world bounds, like on google maps site itself.
I am using javascript google map api v3, here is my map options:
mapOptions = {
center: new google.maps.LatLng(20, 0),
zoom: 3,
minZoom: 3,
zoomControl: true,
I've restricted map zoom, but user still can drag out of world bounds and even select region there.
How can I prevent this behavior?
You have to make a general check using some conditional statement like if...else and comparing if the current Lat/Lng is falling out of a specified boundary (which is a world bound in your case).
I would recommend you to look at this SO question that may provide you some leads of how to proceed.
Found a nice solution I'd like to share:
if (!allowedBounds.intersects(map.getBounds())) {
map.panToBounds(allowedBounds);
}
it will return to the initial set bounds (minimum way) when the whole screen left the bounds.

Displaying Antarctica using GeoJSON in heremaps

I'm trying to render Antarctica geojson shape on a map using the HERE maps api.
The geojson is found here: https://github.com/johan/world.geo.json/blob/master/countries/ATA.geo.json
You can see github renders it nicely.
Using the same geojson on geojson.io also renders it nicely.
But somehow it seems to render the 'inverse' of Antarctica when using it in HERE maps.
It colors everything except antarctica.
see: http://imagebin.ca/v/1dZIn5vsEuFx
(I've tried making an expample using jsfiddle, but it's not able to load external json. And the HERE maps api doesn't allow you to load geoJSON from a string)
Is there an issue with the geoJSON? Is there an issue with the HERE maps api?
The API doesn't quite understand what to do with the open polygon. Because the polygon is basically just a line around the globe the API doesn't know if you shape closes over the north pole or the south pole. By default it assumes that open polygons close over the north pole. You can change this by using this flag (setNorthPoleCovering):
http://developer.here.com/javascript-apis/documentation/v3/maps/topics_api_nlp/h-map-polygon.html#h-map-polygon__setnorthpolecovering
However, actually getting to that point in the code where this can be done is a bit complicated:
// When you instantiate the geojson.Reader you can specify a function that
// receives all objects the reader parsed. It is called when objects are
// being rendered on the map. At that point we can look into the object and
// check whether it is Antarctica
var reader = new H.data.geojson.Reader('...ATA.geo.json', {
style: function(obj) {
if (obj.getData().properties.name === "Antarctica") {
//AHA! We found Antarctica!
// Since this is a multi-polygon we have a group here which contains
// all polygons. We apply the north-pole-covering flag to each of the
// polygons
obj.forEach(function(polygon) {
polygon.setNorthPoleCovering(false);
});
}
}
});
reader.parse();
map.addLayer(reader.getLayer());
Depending on what you want to accomplish in terms of dynamic behavior, if you are just looking to display or share a map with cards and other metadata about a country with some basic styling -- HERE XYZ can be used to render GeoJSON on a HERE map.
If you want to do it with JavaScript rather than an embedded iframe, the other answer may be what you are looking for.
There is an there an issue with the GeoJSON, and other mapping APIs would have the same problem. It needs to be closed at the 180th meridian, so
[178.277212,-84.472518],[180,-84.71338],[-179.942499,-84.721443]
becomes
[178.277212,-84.472518],[180,-84.71338],[180,-90],[-180,-90],[-180,-84.71338],[-179.942499,-84.721443]

Categories

Resources