Mapbox markers flashing when using `icon-allow-overlap` - javascript

I have a map that's using mapboxgl-js to hide or show map markers based on some criteria.
Hiding the markers is working as expected, but when I want the markers to show again they flash for some milliseconds then disappear again while the map hides labels (street names etc.) on the underlying layer before they show up again.
See this video: https://streamable.com/debcp
See this codepen: https://codepen.io/jakobfuchs/details/VRRgJO
I came to the conclusion that this is caused by setting 'icon-allow-overlap': true on the marker symbol layer.
Any suggestions how I can keep that setting and avoid the flashing?
The strange thing is that this does not happen 100% of the time but ~95% of the time.
Code samples:
Marker layer:
map.addLayer({
id: 'property-layer',
type: 'symbol',
source: 'properties',
filter: ['!has', 'point_count'],
layout: {
'symbol-placement': 'point',
'icon-image': 'marker',
'icon-size': 1,
'icon-anchor': 'bottom',
'icon-allow-overlap': true,
}
});
Filter code:
const filterToggle = document.getElementById('filterToggle');
filterToggle.addEventListener('change', function(e) {
if (openPopup) {
openPopup.remove();
openPopup = '';
}
let properties;
if (this.checked) {
properties = {
type: "FeatureCollection",
features: features.features.filter((property) => property.properties.availability === 'Available')
}
} else {
properties = features;
}
map.getSource('properties').setData(properties);
});

I have faced with the same issue and my solution is use the icon-ignore-placement instead of icon-allow-overlap, and it's still not have any issues
You can find the document here: https://docs.mapbox.com/mapbox-gl-js/style-spec/#layout-symbol-icon-ignore-placement
Hope this will help, thanks!

Related

Mapbox, draw polygons of different colors

Using Mapbox GL, I want to be able to create polygons and give them individual colors, but after along search and read through the api doc, just can'tfigure out out this is supposed to be done.
nb: I want to use draw not addlayer as I want the polygon to still be editable afterwards.
nb: this.color is a hex value selected by the user
maybe I'm a newbie n00bing out, maybe the approach isn't quite right.
// when a poly is created add a color property to it and save it into the stagedFeatures array
this.map.on('draw.create', e => {
e.features.forEach(feature => {
feature['properties'] = { color: this.color }
this.stagedFeatures.push(feature)
})
})
// set the color of the next polygon
document.getElementById('colourSelector').addEventListener('change', e => {
if (e.target['value']) {
this.color = e.target['value']
this.setStyle()
}
})
// generate the styles
getStyles() {
return [
{
'id': 'gl-draw-polygon-fill-inactive',
'type': 'fill',
'filter': [
'all',
['==', 'active', 'false'],
['==', '$type', 'Polygon'],
['!=', 'mode', 'static']
],
'paint': {
// my problem is likely here, have tried many expressions etc but mapbox
// expressions aren't super easy to figure out
'fill-color': this.color,
'fill-outline-color': this.color,
'fill-opacity': 0.5
}
},
...
// redraw the map and readd the polygons
setStyle() {
this.map.removeControl(this.draw)
if (typeof this.map.getSource('staged-features') !== 'undefined') {
this.map.removeSource('staged-features')
}
this.map.addSource("staged-features", {
type: "geojson",
data: {
type: "FeatureCollection",
features: this.stagedFeatures
},
})
this.draw = new MapboxDraw({
userProperties: true,
displayControlsDefault: false,
controls: {
polygon: true,
trash: true
},
styles: this.getStyles()
})
this.map.addControl(this.draw)
// loop through any features that the map needs to redraw
this.stagedFeatures.forEach(i => {
console.warn('restore polygons', i)
this.draw.add(i)
})
}
whats happening is the polys redraw but using only the selected color, I'm wanted to get an expression workeing the pulls back the color from the feature.properties.color value
['get', 'color'] with a fallback to this.color doesn't appear to work here.
whats happening is the polys redraw but using only the selected color, I'm wanted to get an expression workeing the pulls back the color from the feature.properties.color value
['get', 'color'] with a fallback to this.color doesn't appear to work here.
https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/
tried the null operators suggested here:
https://github.com/mapbox/mapbox-gl-js/issues/5761

Filter Feature's outside the viewport in Mapbox

I have a huge geojson file having around 100K feature's and I want to filter feature's outside the viewport. I tried multiple approach given on:
https://github.com/mapbox/mapbox-gl-js/issues/8350
and
https://gis.stackexchange.com/questions/300292/how-to-load-geojson-features-outside-view-with-mapbox-gl?rq=1
But nothing seems to work.
My Code is:
//Here i have already added empty geojson source
this.instance.addSource('seats_geojson', {
type: 'geojson',
data: {
"type": "FeatureCollection",
"features": []
}
});
//Here i have axios call with await and i am getting all the feature's in console
//console.log(e.data.featuresCollection.features) <--- 100K features
this.instance.once('idle', () => {
//Once i have the reponse ready I am setting source using setData
this.instance.getSource('seats_geojson').setData(e.data.featuresCollection);
//Here i am creating empty layer with above source
this.instance.addLayer({
id: "rowSelectionDup",
type: 'circle',
source: 'seats_geojson',
paint: {
'circle-color': "#4400d9"
},
filter: [
"in", "s", ""
]
});
});
but on doing something like:
this.instance.querySourceFeatures('seats_geojson', {
sourceLayer: 'rowSelectionDup',
filter: ['in', 's', "1C"] //This section "s" 1C is in viewport and i am getting 207 feature's
});
this.instance.querySourceFeatures('seats_geojson', {
sourceLayer: 'rowSelectionDup',
filter: ['in', 's', "7C"]. //This section is outside viewport and result is []
});
Note: this.instance is the map instance(new Map(config....)) of mapbox-gl
Am I doing something wrong here?
or is there any other approach to get feature's from geojson?
Thank you in advance...
As i posted this question on mapbox-gl Github:
https://github.com/mapbox/mapbox-gl-js/issues/9720
As of current mapbox-gl version, there isn't a direct way to fetch the feature's outside of viewport. Hence, as answered by #steve-bennett, I am fetching the geojson url, save as a reference in the javascript oject and applying filter on it is working for me now...
Hope it helps...

How to add hover effect to new layer created with custom geojson

I've built a map and added a layer that highlights a specific neighborhood, I'd like to add a hover effect to the layer. just like in this example https://docs.mapbox.com/mapbox-gl-js/example/hover-styles
I got as far as creating my own layer with the geojson but the example I am trying to follow uses an external data source whereas I am using my own. I tried to reference my data but I don't think I am doing it correctly. Pleases see this link with a working version showing the layer highlighting the neighborhood.
This is the link to what I have so far https://jsfiddle.net/jrax4pvm/1/
Here's my JS
mapboxgl.accessToken =
'pk.eyJ1IjoibGVvc29ubmVrdXM5NSIsImEiOiJjazAxdHcyZWExMHBjM2lwN2psMDhheXQwIn0.KpEYrurG0lE55PLKMuYtKw';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/leosonnekus95/ck11gbbaz0neb1cmrunqmijkf',
zoom: 15,
center: [174.7570008, -36.8658221]
});
map.on('load', function () {
'id': 'Uptown',
'type': 'fill',
'source': {
'type': 'geojson',
'data': {
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates':
[
[ /* Co-ordinates here..*/ ]]
}
}
},
'layout': {},
'paint': {
'fill-color': '#088',
'fill-opacity': 0.8
}
});
});
I'd really like to make this layer hoverable/clickable and suspect I have to create a combined version of these two examples
https://docs.mapbox.com/mapbox-gl-js/example/geojson-polygon/
https://docs.mapbox.com/mapbox-gl-js/example/hover-styles/
and would like some guidance.
You'll want to add map.on('mouseenter') and map.on('mouseleave') functions which target your layer to your code like this:
map.on('mouseenter', 'Uptown', function(e) {
map.setPaintProperty('Uptown', 'fill-color', '#FF0000');
});
map.on('mouseleave', 'Uptown', function() {
map.setPaintProperty('Uptown', 'fill-color', '#1F06F0'));
});
I've updated your code in another JSFiddle (https://jsfiddle.net/pjleonard37/jfd0bsha/) with these changes.
Disclaimer: I work at Mapbox

Customising Google Map marker

I'm using some code i got from Codepen for placing some pointers on a Goole map.
It's currently using the default markers but id like to change them to my own ones, but i'm not really sure where to updated the code for this. Any examples would be very much appreciated
Here is the the code - http://jsfiddle.net/MSLRr/
Each pointer is placed by this code:
var data = [ // map data
{
'id':1,
'content':'Hello my name is marker, I\'m from Google',
'position': {
'lat':55.86423,
'lng':-4.251
}
},
{
'id':2,
'content':'I am the content of this infobox. Wow, what a text.<br><br>The good thing is: Tags are also possible',
'position': {
'lat':55.874,
'lng':-4.25
}
},
]
You should use icon property of the marker (google dev reference: https://developers.google.com/maps/documentation/javascript/markers#icons)
var data = [ // map data
{
'id':1,
'content':'Hello my name is marker, I\'m from Google',
'position': {
'lat':55.86423,
'lng':-4.251
},
'icon': 'youricon.png'
},
{
'id':2,
'content':'I am the content of this infobox. Wow, what a text.<br><br>The good thing is: Tags are also possible',
'position': {
'lat':55.874,
'lng':-4.25,
},
'icon': 'youricon.png'
}]
And using the new property icon in your data array to markers

How do i capture events onClick of a google maps fusion table layer..?

Hmmm.. I have a map with several points on it. And I'd like to get the latitude and longitude when a point is clicked. How do I do that?
ps. I'm quite new to javascript, so
an example would really help.. T_T
There is something about it in the docs,
I just have no idea how to use it because of my noobness to javascript..
http://code.google.com/apis/maps/documentation/javascript/reference.html#FusionTablesMouseEvent
function initPoints()
{
points = new google.maps.FusionTablesLayer({
query: {
select: "points",
from: poleid
},
styles: [{
markerOptions: {
iconName: "small_green"
}
}],
suppressInfoWindows: true
});
points.setMap(map);
}
Got it..
google.maps.event.addListener(points, 'click', function(event) {
alert("lat:"+ event.latLng.lat());
});

Categories

Resources