In a previous question, someone asked about image overlays with map styles:
How do I add a simple image overlay in Mapbox Javascript?
I got it to work with their example, but I want to use my own style.
Here's a link to my map style.
This is the style they use that works:
mapbox://styles/mapbox/satellite-v9
This is my style, it doesn't work:
mapbox://styles/nittyjee/ck0fasve30an21cpalmwct518
Below is the code that works, you can run it yourself. My style is commented out.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Add an image</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.45.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.45.0/mapbox-gl.css' rel='stylesheet' />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoibml0dHlqZWUiLCJhIjoid1RmLXpycyJ9.NFk875-Fe6hoRCkGciG8yQ';
var map = new mapboxgl.Map({
container: 'map',
maxZoom: 5.99,
minZoom: 4,
zoom: 5,
center: [-75.789, 41.874],
//Style from Stack Overflow:
style: 'mapbox://styles/mapbox/satellite-v9'
//My style does not work:
//style: 'mapbox://styles/nittyjee/ck0fasve30an21cpalmwct518'
});
map.on('load', function() {
map.addSource("myImageSource", {
"type": "image",
"url": "https://docs.mapbox.com/mapbox-gl-js/assets/radar.gif",
"coordinates": [
[-80.425, 46.437],
[-71.516, 46.437],
[-71.516, 37.936],
[-80.425, 37.936]
]
});
map.addLayer({
"id": "overlay",
"source": "myImageSource",
"type": "raster",
"paint": {
"raster-opacity": 0.85
}
});
});
</script>
</body>
</html>
You need to bump up mapbox-gl version. You're using a way older SDK.
Change your script/css definition to this:
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.1/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.1/mapbox-gl.css' rel='stylesheet' />
That doesn't look like a style URL https://docs.mapbox.com/help/glossary/style-url/
You'd need to create a style in Mapbox Studio and grab the style ID.
When you're in Studio looking at your style, you can click on Share in the top right corner.
Then from there, you should see a panel that will have a section called Your style url. If you copy that link and paste it into your code, your style should come through.
You can also click on the 3 dots by your style and copy the style id at the bottom of the panel that appears:
Related
I want to find out buildings inside a runtime-drawed polygon.
And fill with green color.
I try to archive it with feature state and case expression. When I find out those features that inside the polygon in some way, I still can't execute the map.setFeatureState, cause the first parameter need (feature object) need a specified id, however, the feature that created by composite source hasn't set id, also looks there is no way to set 'generateId:true'.
Is there any alternate way to achieve the purpose?
in the follow snippet,there is a polygon draw tool on the top-right,draw a polygon and double click to end of draw, then you will find the error alerted in the console.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#turf/turf#5/turf.min.js"></script>
<link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.0/mapbox-gl-draw.css" type="text/css" />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken =
"pk.eyJ1IjoibWluem9qaWFuIiwiYSI6ImNrbGFsem92MjAxaHAycG1sbGg3MXFsODAifQ.Kclz1IBxyU0iDiVgIjhSYQ";
var map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v11"
});
var map = new mapboxgl.Map({
style: "mapbox://styles/mapbox/light-v10",
center: [-73.991, 40.735],
zoom: 15.5,
pitch: 45,
bearing: -17.6,
container: "map",
antialias: true
});
var draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
polygon: true,
trash: true
}
});
map.addControl(draw);
map.on("draw.create", updateArea);
map.on("draw.delete", updateArea);
map.on("draw.update", updateArea);
function updateArea(e) {
if (map.getLayer("maine")) map.removeLayer("maine");
if (map.getSource("data-area")) map.removeSource("data-area");
map.addSource("data-area", {
type: "geojson",
data: draw.getAll()
});
//get features in polygon
lastInAreaFeatures = map
.queryRenderedFeatures({
layers: ["3d-buildings"]
})
.filter(function(t) {
return turf.booleanContains(
turf.polygon(draw.getAll().features[0].geometry.coordinates),
t.geometry.type == "MultiPolygon" ?
turf.polygon([t.geometry.coordinates[0][0]]) :
turf.polygon([t.geometry.coordinates[0]])
);
});
//try to update state,and set in-area equals true. so that the condition paint logic will work in the bellow "3d-buildings" layer
//////however,the follow code can't work because the id of feature is undefined
///// 'Error: The feature id parameter must be provided.' will alerted in console
lastInAreaFeatures.forEach(function(f) {
map.setFeatureState(f, {
"in-area": true
});
});
console.log(lastInAreaFeatures);
draw.deleteAll();
}
var lastInAreaFeatures;
// The 'building' layer in the mapbox-streets vector source contains building-height
// data from OpenStreetMap.
map.on("load", function() {
map.addLayer({
id: "3d-buildings",
source: "composite",
"source-layer": "building",
filter: ["==", "extrude", "true"],
type: "fill-extrusion",
minzoom: 15,
paint: {
"fill-extrusion-color": [
"case", ["==", ["feature-state", "in-area"], true],
"green",
"#aaa"
],
"fill-extrusion-height": [
"interpolate", ["linear"],
["zoom"],
15,
0,
15.05, ["get", "height"]
],
"fill-extrusion-base": [
"interpolate", ["linear"],
["zoom"],
15,
0,
15.05, ["get", "min_height"]
],
"fill-extrusion-opacity": 0.6
}
});
});
</script>
</body>
</html>
I'm trying to follow the instructions here: https://docs.mapbox.com/mapbox-gl-js/example/simple-map/
My code is as follows, just as in the example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Display a map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" />
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%;}
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = 'MY_TOKEN';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/ericgithinji/ckfchv1sr0u581amw703zg3jh',//it also fails when I use one of the public styles
center: [-74.5, 40], // starting position [lng, lat]
zoom: 9 // starting zoom
});
</script>
</body>
</html>
The div for the map doesn't display anyting, i.e. I get a blank web page. I've followed the tests here for style_id, tileset id, and access token and they all work: https://docs.mapbox.com/help/troubleshooting/blank-tiles/
I have no idea what could be the problem. If it helps,my Index.html is hosted locally on Ubuntu Apache2 server.
I was making two mistakes: 1 - using my secret token instead of my public token and 2 - not generating a style for myself first (it didn't work with the default style from the example).
appreciate some assistance with figuring out why ESRI Tile layer does not load in Leaflet? It loads in OpenLayers and of course when using the ESRI JS API, but I'd like to use Leaflet...
This is the standard Leaflet "Quickstart" example with the Tile Layer url. I've tried many options of both the layer and map constructor and forcing the map to resize and redraw etc, but I can't get it to work...
<html>
<head>
<meta charset=utf-8 />
<title>Esri Leaflet Quickstart</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<!-- Load Leaflet from CDN-->
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet-src.js"></script>
<!-- Load Esri Leaflet from CDN -->
<script src="https://unpkg.com/esri-leaflet#2.0.8"></script>
<style>
body { margin:0; padding:0; }
#map { position: absolute; top:0; bottom:0; right:0; left:0; }
</style>
</head>
<body>
<div id="map"></div>
<script>
function initmap() {
map = new L.Map('map');
//var osmUrl = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}.png'; <- example from Esri-Leaflet that works fine
var osmUrl = 'https://citymaps.capetown.gov.za/agsext1/rest/services/Background_Maps/Relief_Map/MapServer/tile/{z}/{y}/{x}';
var osm = new L.esri.tiledMapLayer({url:osmUrl, noWrap: true});
map.addLayer(osm);
}
var lat = Number(18.5296);
var lng = Number(-33.9597);
var startLatLng = new L.LatLng(lat, lng);
initmap();
map.setView(startLatLng, 0);
</script>
</body>
</html>
OpenLayers example of exactly the same that works:
<!DOCTYPE html>
<html>
<head>
<title>Tiled ArcGIS MapServer</title>
<link rel="stylesheet" href="https://openlayers.org/en/v4.1.0/css/ol.css" type="text/css">
<script src="https://openlayers.org/en/v4.1.0/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script>
var urlRelief = 'https://citymaps.capetown.gov.za/agsext1/rest/services/Background_Maps/Relief_Map/MapServer';
var layers = [
/* new ol.layer.Tile({
source: new ol.source.OSM()
}), */
new ol.layer.Tile({
source: new ol.source.TileArcGISRest({
url: urlRelief,
projection: 'EPSG:4326',
wrapX: false
})
})
];
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center: [2062612, -4026418],
zoom: 10
})
});
</script>
</body>
</html>
i see several different problems going on here:
you shouldn't append /tile/{z}/{y}/{x} to urls when instantiating a tiledMapLayer. we don't do that in our samples.
Leaflet (and consequently Esri Leaflet) only know about the explicit tiling scheme used by Google, Bing etc. your service may reference the same base projection, but it utilizes a non standard tiling scheme (ie: the resolutions and scales differ). in Esri Leaflet we attempt to remap LODs, but only when we recognize the scale and resolution.
standard:
{
"level": 10,
"resolution": 152.87405657041106,
"scale": 577790.554289
},
{
"level": 11,
"resolution": 76.43702828507324,
"scale": 288895.277144
},
{
"level": 12,
"resolution": 38.21851414253662,
"scale": 144447.638572
},
yours:
{
"level": 0,
"resolution": 135.46693760054188,
"scale": 512000
},
{
"level": 1,
"resolution": 67.73346880027094,
"scale": 256000
},
{
"level": 2,
"resolution": 33.86673440013547,
"scale": 128000
}
your best option is to stick with Google's standard tiling scheme even if you want to restrict the area of interest. this can be accomplished pretty easily in ArcGIS Desktop whether you end up publishing tiles to ArcGIS Online, ArcGIS Server or creating a custom tile package.
I'm using Mapbox GL JS version 0.32. Is there a way to export the map to a high-res PNG or PDF?
Obviously, I can just screenshot, but it would be nice if there was a more formal way.
I found this repo, but it looks old and isn't clear how it works.
I tried using the preserveDrawingBuffer option:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
minZoom: 4,
maxZoom: 14,
center: [-2.0, 53.3],
preserveDrawingBuffer: true
});
console.log(map.getCanvas().toDataURL());
This outputs a long data URL in the console, but copying and pasting it into a base64 converter just seems to produce an empty image.
UPDATE: This is my new code, in full:
mapboxgl.accessToken = 'pk.eyXXX';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
minZoom: 4,
maxZoom: 14,
center: [-2.0, 53.3],
preserveDrawingBuffer: true
});
var dpi = 300;
Object.defineProperty(window, 'devicePixelRatio', {
get: function() {return dpi / 96}
});
map.on('load', function () {
var content = map.getCanvas().toDataURL();
console.log(content)
});
The output to the console is this: http://pastebin.com/raw/KhyJkJWJ
There are two main questions:
1. How do I get the map canvas as an image?
Actually, you are doing the right thing, but just too early. Give that map some time to load and fetch the image data when the load event is triggered:
map.on('load', () => console.log(map.getCanvas().toDataURL()));
2. How do I get that image in high-res?
By changing window.devicePixelRatio according to your destination dpi, you can trick your browser into generating high-res output. I found that solution in an implementation created by Matthew Petroff, see his code on https://github.com/mpetroff/print-maps.
This is the trick he's using for generating high-res output:
Object.defineProperty(window, 'devicePixelRatio', {
get: function() {return dpi / 96}
});
Source
I created a simple working example for anybody stumbling upon this thread:
(Thanks #Vic for pointing out the preserveDrawingBuffer-option in Mapbox GL JS)
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Display a map</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.44.1/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css' rel='stylesheet' />
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<style>
#map {
margin: auto;
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<div id='map'></div>
<a id="downloadLink" href="" download="map.png">Download ↓</a>
<div id="image"></div>
<script>
mapboxgl.accessToken = 'your-token-here';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-74.50, 40],
zoom: 9,
preserveDrawingBuffer: true
});
$('#downloadLink').click(function() {
var img = map.getCanvas().toDataURL('image/png')
this.href = img
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Drawing Tools Sample</title>
<!-- Bing Map Control references -->
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<script type="text/javascript">
function GetMap() {
map = new Microsoft.Maps.Map(document.getElementById("myMap"), {
credentials: "",
zoom: 17,
center: new Microsoft.Maps.Location(47.592, -122.332)
});
var infoboxOptions = {
width: 200,
height: 100,
showCloseButton: true,
zIndex: 0,
offset: new Microsoft.Maps.Point(10, 0),
showPointer: true
};
var defaultInfobox = new Microsoft.Maps.Infobox(map.getCenter(), infoboxOptions);
map.entities.push(defaultInfobox);
defaultInfobox.setHtmlContent('<div>MY TEXT <input type="text"></div>');
}
</script>
</head>
<body onload="GetMap()">
<div style="position:relative;width:250px;height:150px;float:left;">
<div id="myMap" style="position:relative; width:600px;height:200px;"></div>
</div>
</body>
</html>
I am looking add custom Html elements such as textbox, textarea to bing map pushpin therefore it can be editable when it placed.
problem is can be place push pin with textbox or textarea but it cannot be editable.
This is a limitation of the default infobox class. You can work around this by using the custom infobox module found here: https://bingmapsv7modules.codeplex.com/wikipage?title=Custom%20Infobox%20Control