How to style a layer - openlayers-5

I am trying to put image icons on my nodes in an openlayers 5 layer, but can't seem to get it right.
I load an osm file and everything is ok, but i get a small circle instead of the icon.
I've searched online and all i can find is how to change a feature icon, not all features of a layer.
Part of my osm file
<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' upload='false' generator='JOSM'>
<node id='-102236' lat='37.1556611' lon='-8.5700716'>
<tag k='vpa_cod' v='784' />
<tag k='vpa_linha' v='11,38,' />
</node>
</osm>
Declaration of layer
new VectorLayer({
source: new VectorSource({
url: './assets/layers/111_.osm',
format: new OSMXML(),
formatOptions: {
extractStyles: true,
extractAttributes: true,
maxDepth: 2
},
style: new Style({
image: new Icon( ({
anchor: [0, 0],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
src: 'assets/images/icons/11.svg',
scale : 0.35
}))
})
})
})
I want to have an icon on my nodes, but only get small circles.

style should be a property of the layer, not the source
new VectorLayer({
source: new VectorSource({
url: './assets/layers/111_.osm',
format: new OSMXML(),
formatOptions: {
extractStyles: true,
extractAttributes: true,
maxDepth: 2
}
}),
style: new Style({
image: new Icon({
anchor: [0, 0],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
src: 'assets/images/icons/11.svg',
scale : 0.35
})
})
})

Related

MapBox GL custom markers with symbol layer

I am trying to cluster custom markers in MapBox GL JS but I cannot figure out how to get a custom marker image from a url into the symbol layer? It either does not work or no markers show up at all. How is it done? I need to know how to use a custom image from a url with the symbol layer. Thank you very much.
map.addSource('parcelpoints', {
type: 'geojson',
data: geojson,
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
});
map.addLayer({
id: 'clusters',
type: 'circle',
source: 'parcelpoints',
filter: ['has', 'point_count'],
paint: {
// Use step expressions (https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step)
// with three steps to implement three types of circles:
// * Blue, 20px circles when point count is less than 100
// * Yellow, 30px circles when point count is between 100 and 750
// * Pink, 40px circles when point count is greater than or equal to 750
'circle-color': [
'step',
['get', 'point_count'],
'#51bbd6',
100,
'#f1f075',
750,
'#f28cb1'
],
'circle-radius': [
'step',
['get', 'point_count'],
20,
100,
30,
750,
40
]
}
});
map.addLayer({
id: 'cluster-count',
type: 'symbol',
source: 'parcelpoints',
filter: ['has', 'point_count'],
layout: {
'text-field': '{point_count_abbreviated}',
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
'text-size': 12
}
});
map.addLayer({
id: 'unclustered-point',
type: 'symbol',
source: 'parcelpoints',
filter: ['!has', 'point_count'],
'layout': {
'visibility': 'visible',
'icon-image': { url: "marker.svg" }
}
});
First you need to:
load the external image with a specific ID, via map.loadImage().
add the image with a specific ID, via map.addImage(https://docs.mapbox.com/mapbox-gl-js/api/map/#map#loadimage).
There is a worked example here: https://www.mapbox.com/mapbox-gl-js/example/add-image/
// If the style's sprite does not already contain an image with ID 'kitty',
// add the image 'cat-icon.png' to the style's sprite with the ID 'kitty'.
map.loadImage('https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Cat_silhouette.svg/400px-Cat_silhouette.svg.png', (error, image) => {
if (error) throw error;
if (!map.hasImage('kitty')) map.addImage('kitty', image);
});
To include your loaded image in a symbol layer will look something like:
map.addLayer({
'id': 'clusters',
'type': 'circle',
'source': 'parcelpoints',
'filter': ['has', 'point_count'],
'icon-image': 'kitty',
...
There is no support for directly loading symbol images from URLs.

Leaflet routing machine not giving the optimal route (by far)

I have issues when trying to show a route on my leaflet map:
L.Routing.control({
router: L.Routing.mapbox(''),
profile:"mapbox/driving",
addWaypoints:false,
waypointMode:'snap',
routeWhileDragging: true,
show:false,
fitSelectedRoutes:false,
plan:false,
draggableWaypoints:false,
lineOptions:{
styles:[ {color: 'black', opacity: 0.8, weight: 6}, {color: 'red', opacity: 1, weight: 2}]
},
waypoints: [
L.Routing.waypoint(L.latLng(28.6114741,77.2112497),"New Dehli"),
L.Routing.waypoint(L.latLng(30.7304186,76.7789926),"Chandigarh"),
L.Routing.waypoint(L.latLng(31.1047637,77.1717752),"Shimla"),
L.Routing.waypoint(L.latLng(31.4493988,77.629702),"Rampur"),
L.Routing.waypoint(L.latLng(31.9755409,78.5961753),"Changoa"),
L.Routing.waypoint(L.latLng(32.2251899,78.0610693),"Kaza"),
L.Routing.waypoint(L.latLng(32.4513357,77.860656),"Hanse"),
L.Routing.waypoint(L.latLng(32.4386919,77.7497997),"losar gompa"),
],
}).addTo(map);
At the 7th waypoint (Hanse), the route is doing a U turn, adding a thousand kms to reach the 8th point that is only a few kms away.
What's going on here? I can't figure it out. Any help is welcome!
Welcome to SO!
This is reproducible with OSMR service instead of Mapbox:
var map = L.map("map").setView([32.4513357, 77.860656], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
L.Routing.control({
//router: L.Routing.mapbox(''),
//profile: "mapbox/driving",
addWaypoints: false,
waypointMode: 'snap',
routeWhileDragging: true,
show: false,
fitSelectedRoutes: false,
plan: false,
draggableWaypoints: false,
lineOptions: {
styles: [{
color: 'black',
opacity: 0.8,
weight: 6
}, {
color: 'red',
opacity: 1,
weight: 2
}]
},
waypoints: [
/*L.Routing.waypoint(L.latLng(28.6114741, 77.2112497), "New Dehli"),
L.Routing.waypoint(L.latLng(30.7304186, 76.7789926), "Chandigarh"),
L.Routing.waypoint(L.latLng(31.1047637, 77.1717752), "Shimla"),
L.Routing.waypoint(L.latLng(31.4493988, 77.629702), "Rampur"),
L.Routing.waypoint(L.latLng(31.9755409, 78.5961753), "Changoa"),
L.Routing.waypoint(L.latLng(32.2251899, 78.0610693), "Kaza"),*/
L.Routing.waypoint(L.latLng(32.4513357, 77.860656), "Hanse"),
L.Routing.waypoint(L.latLng(32.4386919, 77.7497997), "losar gompa"),
],
}).addTo(map);
#map {
height: 200px;
}
<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>
<link rel="stylesheet" href="https://unpkg.com/leaflet-routing-machine#3.2.7/dist/leaflet-routing-machine.css">
<script src="https://unpkg.com/leaflet-routing-machine#3.2.7/dist/leaflet-routing-machine.js"></script>
<div id="map"></div>
It looks like the OSM database thinks there is a "barrier" obstacle near your arrival point ("losar gompa"):
If this obstacle type cannot be crossed by car, that would explain why the router takes another (very long…) route instead.
If you think this obstacle no longer exists, please feel free to create an account on OpenStreetMap and edit the map! There is a very high chance that Mapbox router uses OSM data, therefore your modifications would be reflected some time later in Mapbox.

MapBox markers Move on zooming

I'm working on MapBoxgl and I want to add several markers.
Here is my index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link href=" /assets/css/bootstrap.min.css " rel="stylesheet" />
<link href=" /assets/css/mapbox-gl.css " rel="stylesheet" />
<link href=" /assets/css/main.css " rel="stylesheet" />
</head>
<body>
<div id="map"></div>
<script src="/assets/js/mapbox-gl.js"></script>
<script src="/assets/js/map-style.js"></script>
</body>
</html>
This is map-style.js:
var map = new mapboxgl.Map({
container: 'map',
center: [57.3221, 33.5928],
zoom: 5,
style: style
});
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.61, 46.28]
},
properties: {
title: 'point 1',
description: 'point 1 Description',
message: 'point1',
iconSize: [25, 25]
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.62, 46.2845]
},
properties: {
title: 'point 2',
description: 'point 2 Description',
message: 'point 2',
iconSize: [25, 25]
}
}]
};
map.on('load', function () {
// add markers to map
geojson.features.forEach(function(marker) {
// create a DOM element for the marker
var el = document.createElement('div');
el.className = 'markers';
el.style.backgroundImage = 'url(assets/marker-azure.png)';
//el.style.width = marker.properties.iconSize[0] + 'px';
el.style.height = marker.properties.iconSize[1] + 'px';
el.addEventListener('click', function() {
window.alert(marker.properties.message);
});
// add marker to map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.addTo(map);
});
});
And following is main.css portion related to map and marker:
#map { position:absolute; top:0; bottom:0; width:100% }
.markers {
display: absolute;
border: none;
border-radius: 50%;
cursor: pointer;
padding: 0;
}
So, my problem is that when I add width property to markers, their icon be displayed correctly (with a bit stretch) but they are in wrong coordinate and move on zoom, like picture below:
On the other hand, if width property is eliminated, they are in right place and does not move on zooming, but they are very stretched and in fact as wide as screen (following image):
It's noteworthy that I've used bootstrap. Can it be the reason of this? If not, what's the problem?
Thanks
import 'mapbox-gl/dist/mapbox-gl.css';
Adding import css works for me.
I found the solution and share it here with others who will encounter this problem. The problem caused because of using a not-most-recent version of the library. After upgrading to the latest release, I could get rid of that problem.
Note that these kinds of problems sometimes occur, when you use npm. Make sure that the library is downloaded completely and It's the latest release.
Latest releases of MapBox can be found at here.
had similar issue, the marker seemed to change position on zoom in/out, fixed it by setting offset, thought to share if it can help others, here is the fiddle
// add marker to map
var m = new mapboxgl.Marker(el, {offset: [0, -50/2]});
m.setLngLat(coordinates);
m.addTo(map);
(Using mapbox 1.13.0)
I had a similar issue where the popups weren't displaying and would change position based on zoom.
Mapbox officially states that you need to include the css file to have markers and popups work as expected.
https://docs.mapbox.com/mapbox-gl-js/guides/install/
HOWEVER, you can also copy that css directly into a component and use that as an element. For example:
export default function MarkerMapTest(props) {
const mapContainer = React.useRef(null)
const map = React.useRef(null)
const elemRef = React.useRef(null)
React.useEffect(() => {
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/dark-v10",
center: [151.242, -33.9132],
zoom: 14,
})
const marker = new mapboxgl.Marker({
element: elemRef.current,
})
.setLngLat([151.242, -33.9132])
.addTo(map.current)
}, [])
return (
<div
style={{ width: 600, height: 600, backgroundColor: "gray" }}
ref={mapContainer}
>
<div
style={{
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: "red",
position: "absolute", // !
top: 0, // !
left: 0, // !
}}
ref={elemRef}
/>
</div>
In my case the svg I used had some space around the real content. That way it seemed for me that the marker was moving. A simple fix was to remove the space around the content (e.g. with the "Resize page to drawing or selection" option of inkscape: https://graphicdesign.stackexchange.com/a/21638)
Also it is important to set display: block on the svg-marker. See: https://stackoverflow.com/a/39716426/11603006

Draw the polyline along the path of the map in openlayer3

I following code how to draw the polyline along path of the map, know for the point present in the map will just give the straight line how to get along the path of the lanes
<!DOCTYPE html>
<html>
<head>
<title>Rotation example</title>
</head>
<body>
<div style="width:80%; height:80%; position:fixed; border: 1px solid;" id="map"></div>
<script src="http://openlayers.org/en/v3.11.2/build/ol.js"></script>
<script>
var lineString = new ol.geom.LineString([
[103.986083, 1.350349],
[103.985097, 1.349067]
]);
lineString.transform('EPSG:4326', 'EPSG:3857');
var lineLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [new ol.Feature({
geometry: lineString,
name: 'Line'
})]
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: [255, 255, 0, 0.5],
width: 10
})
})
});
var view = new ol.View({
center: ol.proj.transform([103.986908, 1.353199], 'EPSG:4326','EPSG:3857'),
zoom: 18,
rotation: 68*Math.PI/180
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
lineLayer
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: view
});
</script>
</body>
</html>
Is there any direction service provided by openlayer3 please point to sample to accomplish it
If you have coordinates along the lanes you can use MultiLineString instead of LineString.
You need to use a routing service for such action. You may setup your own service or you may use any online available. here you can find a list of free online routers and decide which one best feet to your needs.
Once you get your root polyline out of the selected service you can then decode (if encoded) and draw your line within your ol3 map.
Also cosider, depending on the service you are going to use, that ol3 offers a class for reading and writing data in the Encoded Polyline Algorithm Format which is described here

custom markers not displaying on mapbox map

I am working with a mapbox map on a web page, and have everything working fine with the map and dropping pins, but cant get custom markers working.
My code that is working for dropping a pin is:
L.mapbox.featureLayer({
type: 'Feature',
geometry: { type:'Point', coordinates:[$longitude, $latitude] },
properties: { title:'My Location', description:'My Description', 'marker-size':'large', 'marker-color':'#cc0000', 'marker-symbol':'building' }
}).addTo(map);
This works and populates the map with my locations.
I have used this code to try and add a custom marker, but this doesnt work:
L.mapbox.featureLayer({
type: 'Feature',
geometry: { type:'Point', coordinates:[$longitude, $latitude] },
properties: { title:'My Location', description:'My Description', icon: { iconUrl: 'https://www.mapbox.com/mapbox.js/assets/images/astronaut1.png', iconSize: [50, 50], iconAnchor: [25, 25], popupAnchor: [0, -25], className: 'dot' } }
}).addTo(map);
I also have multiple pins and other layers on the map that can be turned on or off, and everything is working well, I just cant get this custom marker to work at all!
Does anyone have custom markers working with code like this on mapbox?
I don't think you can specify custom marker options like icon like that in the main GeoJSON properties hash.
I believe you would need to do something like the below instead.
var customIcon = new L.Icon({iconUrl: 'https://www.mapbox.com/mapbox.js/assets/images/astronaut1.png', iconSize: [50, 50], iconAnchor: [25, 25], popupAnchor: [0, -25], className: 'dot' })
L.mapbox.featureLayer(
{
type: 'Feature',
geometry: { type:'Point', coordinates:[$longitude, $latitude] },
properties: { title:'My Location', description:'My Description'}
},
{
pointToLayer: function(feature,latLng) { return L.marker(latLng, {icon: customIcon}}
}).addTo(map);
See https://www.mapbox.com/mapbox.js/api/v2.2.2/l-mapbox-featurelayer/