Icon visible in mapbox studio not showing via mapbox gl - javascript

I uploaded an svg and can view it in the mapbox studio map and can display the tileset with stock icons using mapbox gl. However, when I try to use my icon the points do not draw. The background still draws and in the case of the code below the points using cafe-15 are drawn.
'icon-image': 'cafe-15', // stock symbol shows
'icon-image': 'boxy-hourglass', // my uploaded symbol - does not show
Here's my code:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></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.21.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.21.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:30px; padding:0; }
#map { position:absolute; top:50px; bottom:50px; width:22%; height:42% }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = '{token}';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-73.9517, 40.8001],
zoom: 17
});
map.on('load', function () {
map.addSource('toxsites', {
type: 'vector',
url: 'mapbox://djorgensen.5cvtu32g'
});
map.addLayer({
'id': 'spills',
'type': 'symbol',
'source': 'toxsites',
'source-layer': 'Toxicsites160622',
'filter': ['all', ['==', 'MAP_GROUP', 'SPILLS']],
'layout': {
'visibility': 'visible',
'icon-allow-overlap': true,
'icon-image': 'cafe-15', // stock symbol shows
'icon-size': 1
}
});
map.addLayer({
'id': 'pbs',
'type': 'symbol',
'source': 'toxsites',
'source-layer': 'Toxicsites160622',
'filter': ['all', ['==', 'MAP_GROUP', 'PBS']],
'layout': {
'visibility': 'visible',
'icon-allow-overlap': true,
'icon-image': 'boxy-hourglass', // my uploaded symbol - does not show
'icon-size': 1
}
});
});
</script>
</body>
</html>

Custom icons are associated with specific styles in Mapbox Studio, so you would have to save your style with the uploaded custom boxy-hourglass icon, and then update the style URL:
var map = new mapboxgl.Map({
container: 'map',
style: yourNewStyleURLHere,
center: [-73.9517, 40.8001],
zoom: 17
});
disclaimer - I work at Mapbox

Related

How can I make custom waypoints on water with a click in mapbox

I have a map on my website that just shows the map and the location of me(later this is going to change to the location of an little boat). I want to mark a path in the water so the boat can travel in that exact path, so for example from point A to B to C etc. but I couldn't figure out how to do that with dropbox. So basically an delivery route but then on water. can anyone help me! this is what I have so far:
this is my map.html
<meta charset="UTF-8">
<title>Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1' />
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.7.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.7.0/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute ; top: 56px; bottom: 0; width: 100%; }
#buttons { position: absolute; bottom: 0; margin: 0 0 10px 25px}
</style>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body >
<div id="map"></div>
<div >
<button type="button" class="btn btn-primary" id="buttons">asdasd</button>
</div>
</body>
<script src="../js/map.js">
</script>
</html>
and this is my map.js:
mapboxgl.accessToken = 'my_token';
const map = new mapboxgl.Map({
container: 'map', // container ID
style: 'mapbox://styles/mapbox/streets-v11', // style URL
center: [-96, 37.8], // starting position
zoom: 3 // starting zoom
});
const geolocate = new mapboxgl.GeolocateControl()
map.addControl(geolocate)
map.on('load', function()
{
geolocate.trigger();
});
you just have to store at regular intervals the position of the boat (store it in a simple variable, write it in a file, use an API, use localStorage, everything depends on the use). Then you just have to add a layer of type "line" which will use the different points recorded to draw lines between each point.
Here is a working example https://codepen.io/cladjidane/pen/MWrJjjw
mapboxgl.accessToken =
'pk.eyJ1IjoiY2xhZGppZGFuZSIsImEiOiJjbDA4NmVra3gwMG1jM2dvM3V1djh2NnFwIn0.m8Swm9zWKqf0ozaNcZtISQ'
// Init map
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-122.02991,37.33265],
zoom: 12,
})
// Definition of the configuration for GeolocateControl
let geolocate = new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true,
timeout: 15000,
maximumAge: 0,
},
trackUserLocation: true,
});
map.addControl(geolocate)
// Once the map is loaded
map.on('load', function () {
geolocate.trigger();
// We create a data source - GeoJSON format
const position_boat = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: [],
},
},
],
}
// We add to the map this source
map.addSource('route', {
type: 'geojson',
data: position_boat,
})
// All the magic happens here:
// We push in our source the table of coordinates updated with the method "geolocate".
geolocate.on('geolocate', function (position) {
let newCoordinates = [position.coords.longitude, position.coords.latitude]
position_boat.features[0].geometry.coordinates.push(newCoordinates)
map.getSource('route').setData(position_boat)
})
// We add the layer that displays the source on the map
map.addLayer({
id: 'route',
type: 'line',
source: 'route',
layout: {
'line-join': 'round',
'line-cap': 'round',
},
paint: {
'line-color': 'red',
'line-width': 8,
},
})
})

Don't alow user to navagition or zoom out the area ARCGIS

require(["esri/Map", "esri/views/MapView"], function(Map, MapView) {
var map = new Map({
basemap: "topo-vector"
});
//create mapview
var view = new MapView({
container: "viewDiv",
map: map,
zoom: 4,
center: [106.206230, 15.047079],
constraints: {
rotationEnabled: false,
geometry: { // geo
type: "extent",
xmin: 97.539469,
ymin: 25.084159,
xmax: 114.382060,
ymax: 6.848810
},
}, // longitude, latitude
});
});
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
<link href="https://js.arcgis.com/4.18/esri/themes/light/main.css" rel="stylesheet" />
</head>
<script src="https://js.arcgis.com/4.18/"></script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
I want users to just navigate and zoom in on the area that I choose. I use geometry but it doesn't work, users still can zoom out the area. It's there any way to achieve that feature?
Your attempt was good but not enough. The constraints property is useful for scales and zoom, but in your case will not be good for a an area. The reason is that the extent of constraints property is to permit lateral movement.
So, I propose you to use constraints property for zoom levels and use a custom logic to maintain the user in a certain area. The code I made for you is just one example, listen to changes on the view and act accordingly. In this case I check if view center point is in the desire extent, if not I correct it.
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>ArcGIS API for JavaScript Hello World App</title>
<style>
html, body, #viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/css/main.css">
<script src="https://js.arcgis.com/4.18/"></script>
<script>
require([
'esri/Map',
'esri/views/MapView',
'esri/Graphic',
'esri/geometry/Extent',
'esri/geometry/SpatialReference'
], function(Map, MapView, Graphic, Extent, SpatialReference) {
const map = new Map({
basemap: 'topo-vector'
});
const extent = new Extent({
xmin: 97.539469,
ymin: 25.084159,
xmax: 114.382060,
ymax: 6.848810,
spatialReference: new SpatialReference({ wkid: 4326 })
});
const view = new MapView({
container: 'viewDiv',
map: map,
zoom: 8,
center: [106.206230, 15.047079],
constraints: {
minZoom: 8,
maxZoom: 10
}
});
view.graphics.add(
new Graphic({
geometry: extent,
symbol: {
type: 'simple-fill',
fill: 'none',
outline: {
color: 'red',
width: 2
}
}
})
);
view.watch('updating', function(value) {
if (!value && view.center) {
const c = view.center.clone();
if (c.longitude < extent.xmin) {
c.longitude = extent.xmin;
} else if (c.longitude > extent.xmax) {
c.longitude = extent.xmax;
}
if (c.latitude > extent.ymin) {
c.latitude = extent.ymin;
} else if (c.latitude < extent.ymax) {
c.latitude = extent.ymax;
}
if (!c.equals(view.center)) {
view.goTo({ center: c }, { duration: 0 });
}
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>

Mapbox GL snap GPS coordinates do road

I use Mapbox to show on map the path that the user traveled (with my app on phone). My application saves the GPS position regularly, which I then show on the map with the help of Mapbox GL.
<script>
mapboxgl.accessToken = 'pk.XXX';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [aa.AAA, bb.BBB],
zoom: 18
});
var popup = new mapboxgl.Popup()
.setText("XXX YYY")
.addTo(map);
var marker = new mapboxgl.Marker()
.setLngLat([aa.AAA, bb.BBB])
.addTo(map)
.setPopup(popup);
map.on('load', function () {
map.addSource('route', {
'type': 'geojson',
'data': {
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'LineString',
'coordinates': [
[xx.XXX,yy.YYY],
[xx.XXX,yy.YYY],
[xx.XXX,yy.YYY]
}
}
});
map.addLayer({
'id': 'route',
'type': 'line',
'source': 'route',
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': '#888',
'line-width': 8
}
});
});
</script>
I would like Mapbox to snap the position to the road on the map. Something like "snap-to-road" in Google Maps.
I know that Mapbox has something called "map matching". Only I want to list many intermediate points (not just the beginning and the end), and I would like everyone with them to be snaped to the road on the map.
Is something like this possible? Maybe there are some other mapping solutions that can do that?
Take a look at my solution below. It uses Mapbox map matching, then extracts the tracepoints from the response object and draws them on the map.
To make it work on your end, just replace <ACCESS_TOKEN> with your Mapbox access token.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Map Matched Coordinates</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 = '<ACCESS_TOKEN>';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-117.17292,32.71256],
zoom: 15
});
map.on('load', function () {
// map matching request
var matched_coordinates = [];
// Create
let xhr = new XMLHttpRequest();
// GET REQUEST
xhr.open('GET', 'https://api.mapbox.com/matching/v5/mapbox/driving/' +
'-117.17282,32.71204;-117.17288,32.71225;-117.17293,32.71244;-117.17292,32.71256;-117.17298,32.712603;-117.17314,32.71259;-117.17334,32.71254' +
'?access_token=<ACCESS_TOKEN>' +
'&geometries=geojson');
// After Response is received
xhr.onload = function() {
if (xhr.status != 200) {
// NOT SUCCESSFUL
} else {
// SUCCESSFUL
var response = JSON.parse(xhr.response);
var tracepoints = response["tracepoints"];
for(var i = 0; i < tracepoints.length; i++){
matched_coordinates.push(tracepoints[i]["location"]);
}
map.addSource('route', {
'type': 'geojson',
'data': {
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'LineString',
'coordinates': matched_coordinates
}
}
});
map.addLayer({
'id': 'route',
'type': 'line',
'source': 'route',
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': '#888',
'line-width': 8
}
});
}
}
xhr.send();
});
</script>
</body>
</html>

mapbox: How to get light default map?

Currently, I have developing angular app which has map box integrated, I have followed the mapbox instructions but unable to get the desired output.
Can someone guide me that how to achieve following map?
<div class="row">
<mgl-map
renderWorldCopies="false"
[style]="'mapbox://styles/mapbox/light-v10'"
[zoom]="[0]"
[center]="center"
>
<mgl-image
id="blue"
url="../../../../../assets/images/blue.png"
(loaded)="imageLoaded = 'true'"
>
</mgl-image>
<mgl-image
id="red"
url="../../../../../assets/images/red.png"
(loaded)="imageLoaded = 'true'"
>
</mgl-image>
</mgl-image>
<mgl-geojson-source
id="points"
[data]="countryCoordinatesList"
></mgl-geojson-source>
<ng-container *ngIf="imageLoaded">
<mgl-layer
(click)="onClick(row)"
*ngFor="let row of countryList"
[id]="toStringNum(row?.properties?.id)"
type="symbol"
[source]="{
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
row.geometry.coordinates[0],
row.geometry.coordinates[1]
]
}
}
}"
[layout]="{
'icon-image': row.properties.icon,
'icon-size': 0.4,
'icon-allow-overlap': true
}"
></mgl-layer>
</ng-container>
<mgl-layer
id="points"
source="points"
type="symbol"
[layout]=""
></mgl-layer>
</mgl-map>
Thanks in advance
To make your map look exactly like yours, you would have to modify the style a bit, however using this style
mapbox://styles/mapbox/light-v10
the below code should give you a map somewhat similar to what you showed. You would have to change the position of the markers and the marker image to match yours.
Also. please make sure to replace <YOUR_ACCESS_TOKEN> by your token.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Draw GeoJSON points</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 = '<YOUR_ACCESS_TOKEN>';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-96, 37.8],
zoom: 3
});
map.on('load', function () {
// Add an image to use as a custom marker
map.loadImage(
'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png',
function (error, image) {
if (error) throw error;
map.addImage('custom-marker', image);
// Add a GeoJSON source with 2 points
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
// feature for Mapbox DC
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [
-77.03238901390978,
38.913188059745586
]
},
'properties': {
'title': 'Mapbox DC'
}
},
{
// feature for Mapbox SF
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-122.414, 37.776]
},
'properties': {
'title': 'Mapbox SF'
}
}
]
}
});
// Add a symbol layer
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': 'custom-marker',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
}
);
});
</script>
</body>
</html>

Can't add markers to mapbox map with mapbox-gl.js

I am desperately trying to add some markers to a mapbox map by using the mapbox-gl-js with typescript and I follwed several tutorials from the mapbox site, but it doesn't work for me.
mapboxgl.accessToken = 'mykey';
this.map = new mapboxgl.Map({
container: 'map',
style: this.style,
zoom: 13,
center: [12, 12]
});
this.map.on('load', (event) => {
this.map.addSource('testSrc', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ 12, 12]
},
properties: {
title: 'Mapbox',
description: 'Washington, D.C.'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.414, 37.776]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
}]
}
});
this.map.addLayer({
id: 'testSrc',
source: 'testSrc',
type: 'circle',
layout: {
'text-field': '{message}',
'text-size': 24,
'text-transform': 'uppercase',
'icon-image': 'rocket-15',
'text-offset': [0, 1.5]
},
paint: {
'text-color': '#f16624',
'text-halo-color': '#fff',
'text-halo-width': 2
}
});
this.map.addControl(new mapboxgl.NavigationControl());
});
I created a source with some static data and I set it to a layer of the mapboxgl map-object.
The map is displaying without any problems, but I can't add some markers with the required geojson format.
My goal is to dynamically add markers, but here I stuck in adding some static ones.
Do you have any idea what's the problem in here?
Regards Marko
You have two main ways to add "markers" to Mapbox GL JS,
using Marker, example https://docs.mapbox.com/mapbox-gl-js/example/custom-marker-icons/ which will add the image a DOM Element.
using Symbol, example https://docs.mapbox.com/mapbox-gl-js/example/center-on-symbol/ which will add the image as part of the WebGL canvas. You need to ensure the image you use is loaded, eg. https://docs.mapbox.com/mapbox-gl-js/example/add-image/
Try this - this worked for me (delete the popup bit if you don't want it)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title> My Map </title>
<!--This where you put all your dependencies-->
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title> My Map </title>
<!--This where you put all your dependencies-->
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.css' rel='stylesheet' />
<style>
/*this CSS section is where you style your page*/
/*this is how you comment in CSS*/
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
.marker {
background-image: url('mapbox-icon.png');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
.mapboxgl-popup {
max-width: 200px;
}
.mapboxgl-popup-content {
text-align: center;
font-family: 'Open Sans', sans-serif;
}
</style>
</head>
<body>
<div id='map'></div>
<!--The below script section is a javascript section in your html file-->
<script>
//This is where you put your Javascript for interaction
mapboxgl.accessToken = 'pk.eyJ1IjoiY3dpbG1vdHQiLCJhIjoiY2s2bWRjb2tiMG1xMjNqcDZkbGNjcjVraiJ9.2nNOYL23A1cfZSE4hdC9ew'; //Put your own mapbox token
var map = new mapboxgl.Map({
container: 'map', // container id specified in the HTML
style: 'mapbox://styles/cwilmott/ckbowmfzd3r761il84bnji13t' //change to your style
});
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {
time: '2020-06-19T09:47:13Z',
title: '10:47:13',
description: '19 Jun 2020 at 10:47:13'
},
geometry: {
type: 'Point',
coordinates: [
-2.219255366395865,
53.457215089777584,
]
}
},
{
type: 'Feature',
properties: {
time: '2020-06-19T09:47:19Z',
title: 'home',
description: '19 Jun 2020 at 10:47:19'
},
geometry: {
type: 'Point',
coordinates: [
-2.219227672420135,
53.457351307993434
]
}
}]
}
// add markers to map
geojson.features.forEach(function(marker) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
});
</script>
</body>
</html>
If you want to add an external GeoJson, delete the features in the var geojson section and instead put:
var geojson = {
type: 'geojson',
data: 'path-to-your-file.geojson'
}
(I think that should work).

Categories

Resources