Use polyline in google-maps-react? - react-google-maps

I am using google-maps-react in my react program. Is there any way to draw polyline between the plotted markers any in-bulid method to make line between the markers

Import Polyline from react-google-maps and then inside your <GoogleMap></GoogleMap> place something like:
<Polyline
path={pathCoordinates}
options={{
strokeColor: '#00ffff',
strokeOpacity: 1,
strokeWeight: 2,
icons: [{
icon: "hello",
offset: '0',
repeat: '10px'
}],
}}
/>
And then pass some locations to pathCoordinates e.g.
pathCoordinates:[
{lat:50, lng:1},
{lat:50.1, lng:1.1},
]

yes you can all you need to do is add the points to your path inside the options.
<Polyline geodesic={true}
options={{
path: props.route,
strokeColor: '#00ffff',
strokeOpacity: 1,
strokeWeight: 6,
icons: [{
offset: '0',
repeat: '10px'
}],
}}
/>
where props.route looks something like this
[
{"lat": 3.028846373870724, "lng": 101.62019493865353},
{"lat": 3.0293392107899226, "lng": 101.62000181960445},
{"lat": 3.0297677644503347, "lng": 101.61980870055538},
{"lat": 3.0301963179410842, "lng": 101.61967995452267},
{"lat": 3.0307105819060256, "lng": 101.6194868354736},
{"lat": 3.0319319578431805, "lng": 101.61916497039181}
]

Related

Symbol placed with line-center doesn't rotate as the map rotates

I'm having a problem rotating an image with property symbol-placement set to line-center.
This is what it looks like
Removing the property half-solve the issue; the icon rotate as I rotate the map, but they position at the start of the line, and it's not what I'm trying to do.
The definition of my layer is:
{
"id": "my_symbol",
"type": "symbol",
"source": "XXXX",
"source-layer": "XXXXXXX",
"minzoom": 19,
"layout": {
"symbol-placement": "line-center",
"icon-size": {
"stops": [
[20, 0.2],
[21, 0.1],
[22, 0.3],
[23, 0.5],
[24, 0.7]
]
},
"icon-image": [
"concat",
"edge_",
["get", "status_list"]
],
"icon-allow-overlap": true
}
}
I'm trying to achieve this behaviour only by the layer's definition.
I tried looking for a solution, here on SO and on some other sites but I haven't found anything that would help me.
you can set your icon rotation with icon-rotation-alignment
setting it to viewport will fix the icon rotation to your viewport while setting it to map won't rotate it
i'm sorry the gif is hard to see!
{
"id": "my_symbol",
"type": "symbol",
"source": "XXXX",
"source-layer": "XXXXXXX",
"minzoom": 19,
"layout": {
"symbol-placement": "line-center",
"icon-size": {
"stops": [
[20, 0.2],
[21, 0.1],
[22, 0.3],
[23, 0.5],
[24, 0.7]
]
},
"icon-image": [
"concat",
"edge_",
["get", "status_list"]
],
"icon-allow-overlap": true,
"symbol-placement": "line-center",
"icon-rotation-alignment": "viewport"
}
}

How filter features by status

I want to show in my map in a cluster layer filtering by if is opened or not. How can do it? Should I create two layers?
One with filter: filter["has", "opened"] and other with filter: filter["!", ["has", "opened"]]?
export const clusterLayerOpened = {
id: "clusters",
type: "circle",
source: "earthquakes",
filter: ["has", "opened"],
paint: {
"circle-color": [ "step", ["get", "opened"], "#51bbd6",100,"#f1f075",750,"#f28cb1", ],
"circle-radius": ["step", ["get", "opened"], 20, 100, 30, 750, 40],
},
};
export const clusterLayerNoOpened = {
id: "clusters",
type: "circle",
source: "earthquakes",
filter: ["!", ["has", "opened"]],
paint: {
"circle-color": [ "step", ["get", "opened"], "#51bbd6",100,"#f1f075",750,"#f28cb1", ],
"circle-radius": ["step", ["get", "opened"], 20, 100, 30, 750, 40],
},
};
This is my geojson:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"id": "ak16994521",
"mag": 2.3,
"time": 1507425650893,
"felt": null,
"tsunami": 0,
"opened": true
},
"geometry": {
"type": "Point",
"coordinates": [-151.5129, 63.1016, 0.0]
}
},
{
"type": "Feature",
"properties": {
"id": "ak16994519",
"mag": 1.7,
"time": 1507425289659,
"felt": null,
"tsunami": 0,
"opened": false
},
"geometry": {
"type": "Point",
"coordinates": [-150.4048, 63.1224, 105.5]
}
}
]
}
It's not necessary to create two separate layers to filter by whether the a point has been opened or not. Here is some code showing how to add a layer which displays all points with the property "opened": true, and hides all points with "opened": false:
map.addLayer({
'id': 'opened',
'type': 'circle',
'source': 'points',
'paint': {
'circle-radius': 10,
'circle-opacity': ["match", ["to-string", ["get", "opened"]], 'true', 1 , 'false', 0, 0]
}
});
To instead show all points with the property "opened": false, you can switch the 'circle-opacity' expression to read:
["match", ["to-string", ["get", "opened"]], 'true', 0 , 'false', 1, 0]
This code makes use of a few Mapbox expressions. I've linked the documentation to each relevant expression here: match, to-string, and get.
Here is a JSFiddle where two layers are added to the map: https://jsfiddle.net/hpkzrm4n/. The points with "opened": true are shown in red and the points with "opened": false are shown in blue. Note that you will need to add your own Mapbox access token where indicated in order to view the results. Here is a screenshot, as a preview:

Extrude land in MapBox

I am trying to emphasize the fact that the land is higher than the water in my map so wanted to add an extrusion to the land layer. I thought taking the https://docs.mapbox.com/mapbox-gl-js/example/3d-buildings/ of the one with buildings and changing the layer source to 'land' would work but it didn't. Is this something specific to building layers or am I doing something wrong? Here is my layer definition in my style JSON:
{
"id": "3d-land",
"source": "composite",
"source-layer": "land", # Changed this from building
"filter": ["==", "extrude", "true"],
"type": "fill-extrusion",
"minzoom": 0,
"paint": {
"fill-extrusion-color": "#000",
"fill-extrusion-height": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, 30.0
],
"fill-extrusion-base": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, ["get", "min_height"]
],
"fill-extrusion-opacity": 0.8
}
}
First reason is as the console says, "land" does not exist on source "composite". "land" layer is background layer which is exist separately in the style. You cannot use fill-extrusion for background layer. You may want to use layers which use "compose" source.
The other reason is from filter. "filter": ["==", "extrude", "true"] means filtering if the value of layer's property called "extrude" is "true". land layer doesn't have a property extrude so it's always false.
So, the result of fix would be looks like:
map.addLayer(
{
id: "3d-landcover",
source: "composite",
"source-layer": "landcover",
"type": "fill-extrusion",
"minzoom": 0,
"paint": {
"fill-extrusion-color": "#000",
"fill-extrusion-height": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, 30.0
],
"fill-extrusion-base": [
"interpolate", ["linear"], ["zoom"],
15, 0,
18.0, ["get", "min_height"]
],
"fill-extrusion-opacity": 0.8
}
}
);
As the first reason, all the layers except water should be added as above if you want to make the land higher than water. it's not very effective.

Possible to show a subset of the points using one datalayer with mapbox-gl-js?

I have datalayer consisting of points/ markers in Mapbox-gl-js. When I would like to split my points into categories I can use data-styling, for example like this:
"source-layer": "sf2010",
"paint": {
"circle-radius": {
"base": 1.75,
"stops": [[12, 2], [22, 180]]
},
"circle-color": {
property: 'ethnicity',
type: 'categorical',
stops: [
['White', "#fbb03b"],
['Black', '#223b53'],
['Hispanic', '#e55e5e'],
['Asian', '#3bb2d0'],
['Other', '#ccc']]
}
It seems, using one datalayer, all points (possibly with different category-stylings) will be included on the map. I can style a category of points to not show by giving it a circle-radius of zero, but then it still reacts to clicks etc. Or is there a way to really present a subset of the points using one datalayer?
As Molly suggested, you want a filter:
"source-layer": "sf2010",
"paint": {
"circle-radius": {
"base": 1.75,
"stops": [[12, 2], [22, 180]]
},
"circle-color": {
property: 'ethnicity',
type: 'categorical',
stops: [
['White', "#fbb03b"],
['Black', '#223b53'],
['Hispanic', '#e55e5e'],
['Asian', '#3bb2d0'],
['Other', '#ccc']]
}
},
"filter": ['!==', 'ethnicity','Martian']

Q: how to add "fade in" transition effect for Mapbox circle layer

I'm loading points from Geojson in batches and would like to add "fadeIn" effect or animation when the points first appear in Mapbox.
this.map.addLayer({
id: 'points',
type: 'circle',
paint: {
'circle-radius-transition': {duration: 300},
'circle-color': '#F98200',
'circle-stroke-color': '#D23B00',
'circle-stroke-opacity': 0.5,
},
source: 'points',
})
I tried circle-radius-transition but it does not seem to help.
You are on the right track with the paint properties. I think what you need is the circle-opacity-transition.
Follow these steps:
Add the points with 'circle-opacity': 0 as default opacity value
Set the 'circle-opacity-transition' as you wish
After the map is loaded change the layers 'circle-opacity' to 1 and your layer will be faded in.
map.addLayer({
"id": "point",
"source": "point",
"type": "circle",
"paint": {
"circle-radius": 20,
// here we define defaut opacity is zero
"circle-opacity": 0,
"circle-opacity-transition": {duration: 2000},
"circle-color": 'red'
}
});
You can check out this solution here: codepen
Joel's answer was perfect but the timeout has to be places inside the map load function else the circle layer will not be loaded if the map takes more time to load
Checkout the below code snippet
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9lbHN0dWVkbGUiLCJhIjoiY2ltbmI1OWNpMDAxNnV1bWFtMnpqYWJndyJ9.uDWVjgzU7EVS63OuVWSRuQ';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v9', //stylesheet location
center: [7.445683, 46.945966], // starting position
zoom: 9 // starting zoom
});
// the data we'll add as 'points'
var data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"timestamp": "0",
"location-name": "Bern"
},
"geometry": {
"type": "Point",
"coordinates": [7.445683, 46.945966]
}
}]
}
// so if the map loads do the following
map.on('load', function() {
// add the data source with the information for the point
map.addSource('point', {
"type": "geojson",
"data": data
});
map.addLayer({
"id": "point",
"source": "point",
"type": "circle",
"paint": {
"circle-radius": 20,
// here we define defaut opacity is zero
"circle-opacity": 0,
"circle-opacity-transition": {
duration: 1500
},
"circle-color": 'red'
}
});
//Timeout shoud be within the map load function
setTimeout(function() {
map.setPaintProperty('point', 'circle-opacity', 1);
}, 1);
});
<!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.36.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.36.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>
</body>
</html>
Unfortuntely the property-transition won't work in some cases, for example, when you want to toggle a layer on hover.
At least, in my case it does not work. This is my code, the elements pop like there's nothing.
map.addLayer({
'id': 'places-details',
'type': 'symbol',
'source': 'places',
'layout': {
'icon-image': '{icon}',
'text-field': '{data}',
'icon-size': .8,
'text-anchor': 'center',
},
'paint': {
'text-color': '#ffffff',
'icon-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1, 0
],
'text-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1, 0
],
"text-opacity-transition": {
"duration": 3000,
"delay": 0
},
"icon-opacity-transition": {
"duration": 300,
"delay": 0
}
},
});