Rare effect when toggling BaseLayer in leaflet with react-leaflet - reactjs

My application shows a map with react-leaflet and uses LayersControl to switch between an OSM TileLayer and HERE TileLayer. The code is as follows:
<LayersControl position="topright">
<LayersControl.BaseLayer
name={this.props.intl.formatMessage({id:'map.normal_map'})}
checked={true}
>
{ tileLayerOSM }
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name={this.props.intl.formatMessage({id:'map.terrain_map'})}>
{ tileLayerHERE }
</LayersControl.BaseLayer>
</LayersControl>
The problema I see is the following: when moving the OSM map, some 'squares' are downloaded from HERE while they are not ready with OSM. See the network trace:
I would like to avoid this behavior, since it is a bit annoying for the user, who see changes in the visualization for a short period of time.

I don't have experience using Leaflet with React, but these is clearly not the desired behaviour.
In Leaflet that (retrive the both base layers at the same time) happens when you add both to the map. Something like:
const accessToken = 'foo';
let osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
const mapbox = 'https://api.mapbox.com/styles/v1/mapbox/basic-9/tiles/256/{z}/{x}/{y}?access_token={accessToken}';
const map = L.map('map').setView([42.2, -8.8], 12);
map.addLayer(osm);
map.addLayer(mapbox); // only one should be added to the map
or directly when instantiating the map:
let map = L.map('map', {
center: [42.2, -8.8],
zoom: 12,
layers: [osm, mapbox] // only one should be added to the map
});
With this kind of baselayers you only must add one to the map and use the layer control to switch between one or the other. When only one is added only the tiles for one of the maps are requested, saving bandwith.
As a "shot in the dark" I will try to make the checked value explicit for all layers. First both as a harcoded false, nothing should be shown in the map. Then one with checked=true harcoded and the other with false, and so on. Probably the trouble is how those attributes are managed.

Related

How to invert the Toner layer in a Stamen map?

I am trying to invert the toner layer here, and maybe add a color tint to it as well as you can see here on Map Stack : http://mapstack.stamen.com/edit.html#toner[invert=1,tint=$1e88e5#100]/11/37.7547/-122.3513
Although, I'm not sure how would I use that url as a parameter since I don't see it reflect on the map instance.
The API in OpenLayers has no information on how to manipulate the Stamen map.
The Code
<TileLayer
id="nightmode"
title="Night Mode"
source={
new Stamen({
layer: 'toner',
params: {
layers: "",
format: "image/png",
tiled: true
}
})
}
/>
In OpenLayers 6 similar to the grayscale OSM in this example https://openlayers.org/en/main/examples/semi-transparent-layer.html you could specify a className for the layer and use an invert css filter https://codesandbox.io/s/gifted-newton-mk9th?file=/main.js
An alternative would be to use a globalCompositeOperation similar to https://codesandbox.io/s/globalcompositeoperation-fktwf

Azure maps layers are getting on top of each other

I'm using azure map.
What's happening is that I have 2 layers. A layer that have Circles and a layer with polygons.
I have a functionality in which a popup appear when I click on a specific circle.
The issue occur when I add the polygon layer after the circle layer.
It's like the polygon layer is being drawn on top of the circle layer. In which it prevent the popup from appearing when clicking on the circle.
Here's how I'm adding the polygon layer:
showFetchedResultOnMap(facilities) {
const self = this;
if (facilities && facilities.length > 0) {
self.cleanRestrictionLayer();
//Create a data source and add it to the map.
self.datasource = new atlas.source.DataSource();
self.map.sources.add(self.datasource);
//Add a data set to the data source.
self.CleanMap();
//Create a data source and add it to the map.
var datasource = new atlas.source.DataSource();
self.map.sources.add(datasource);
self.map.imageSprite.add(self.chosenCategory, 'assets/svg/' + self.chosenCategory + '.svg')
.then(function () {
facilities.forEach(cat => {
datasource.add(new atlas.data.Feature(new atlas.data.Point([cat.longitude, cat.latitude])));
});
//Add a layer for rendering point data as symbols.
self.map.layers.add(new atlas.layer.SymbolLayer(datasource, self.chosenCategory, {
iconOptions: {
//Pass in the id of the custom icon that was loaded into the map resources.
image: self.chosenCategory,
//Optionally scale the size of the icon.
size: 0.1
}
}));
});
}
}
Anyone have an Idea about how I can fix this??
I'm not seeing a polygon layer in the code you provided. That said, when you add layers to the map, the order in which you add them is the z-index by default. Last one added goes on top. That said, when adding the layer using the map.layers.add function, there is a second parameter you can add in which can be another layer or layer id. When this is specified the layer you are adding will be inserted below that second specified layer. Here is the doc on this: https://learn.microsoft.com/en-us/javascript/api/azure-maps-control/atlas.layermanager?view=azure-maps-typescript-latest#add-layer---layer----string---layer-
Here is a short example:
map.layers.add(new atlas.layers.BubbleLayer(datasource, 'myBubbles'));
map.layers.add(new atlas.layers.PolygonLayer(datasource, 'myPolygons'), 'myBubbles');

Adding and Deleting Multiple Polygons in Google Maps with React - Getting Refs Right

I'm using google-map-react (not react-google-maps), and is able to insert polygons by calling a function polygonDraw within my main Component (not using drawingManager). My function polygonDraw can be seen below.
I can immediately delete the newest polygon by adding polygon.setMap(null) inside my polygonDraw function.
But here is the problem:
I can't delete previously added polygons or all polygons. My need is to be able to delete all polygons and do this without dependency on event handlers (like a click event on a polygon).
I tried different approaches, but had no successful implementation, including:
I'm not able to construct a Polygon component that render new google.maps.Polygon({.etc.}) objects (based on state/props).
As I'm able to insert polygons with my polygonDraw function my current thinking for strategy is:
To establish a reference for each added polygon. I tried implementing React references, including Callback refs and using React.createRef. But no success. My polygonDraw is inside the main component, but outside the render. I can't figure out if it's possible to establish and store a reference to each added polygon, so reference.setMap(null) can be called for each. And if it is possible I don't know how to establish the reference (code inside constructor?, code inside polygonDraw?, code inside render including GoogleMapReact?)
Any help/advice is appreciated :-)
polygonDraw = () => {
let polygonCoords = [{lat: this.state.lat, lng: this.state.lng}, {.etc.}, {.etc.}]
const polygon = new google.maps.Polygon({
paths: [polygonCoords],
fillColor: 'rgb(255, 215, 0)',
});
polygon.setMap(this.state.map.map);
}
render() {
return (
<GoogleMapReact
.etc.
></GoogleMapReact>
)}
I don't know if it cuts down to performance issues, but what about saving the polygons into an array.
// You have to create a store (eventually in the state?)
const polygons = [];
polygonDraw = () => {
let polygonCoords = [{lat: this.state.lat, lng: this.state.lng}, {.etc.}, {.etc.}]
const polygon = new google.maps.Polygon({
paths: [polygonCoords],
fillColor: 'rgb(255, 215, 0)',
});
polygon.setMap(this.state.map.map);
// Then use this to save it to the polygons
polygons.push(polygon);
// OR this if you want
polygons.push({identifyer: "foo", polygon});
}
Afterwards you can just filter through the polygons array and delete the polygons you need.
I don't know if this solution will work, but you can give it a try :)

width and height doesnt change after rotating the screen in react native

I am working on a RN app and I have an issue regarding the rotation and dimensions of the screen. I have a gallery application where I show three images in a row if the screen is vertical. I adjust it by dividing the width by the size of the image, I think this way of specifying the number of images in a row makes it consistent and changeable for different devices. However, after I rotate the screen, I was expecting to see more images in a row, but I didn't. I realized the width didn't change, so I saw three images again instead of 5 or 6. I am not sure if the way I am doing this is right or wrong. Any suggestions regarding this?? Also, how can I change the width and height dynamically, so that I can change the aligning of my gallery after rotation?
here is a part of my code
...var {height, width} = Dimensions.get('window');
var imageSize = 120;
// number : number of images in a row
var number = Math.round(width/imageSize);
console.log(number);
var CameraRollView = React.createClass({
propTypes: propTypes,
getDefaultProps: function(): Object {
return {
groupTypes: 'SavedPhotos',
batchSize: 5,
imagesPerRow: number,
assetType: 'Photos',
renderImage: function(asset) {
//var imageSize = 120;
var imageStyle = [styles.image, {width: imageSize, height: imageSize}];
return (
<TouchableHighlight onPress={
()=>{
/**fire gallery action selectImage*/
this.selectImage(asset.node.image.uri, this.images);
}
} key={asset.node.image.uri}>
<Image
source={asset.node.image}
style={imageStyle}
/>
</TouchableHighlight>
);
},
};
},
...
here what important is -imagesPerRow- I want it to be dynamic, as I rotate the device.
I would recommend against using the Dimensions module if you need to respond to screen size changes.
The View component provides an onLayout property that is called each time that View's layout has to be recalculated (e.g. on device rotation). I don't know anything about the architecture of your app, so I will just say the easiest way to use it in my opinion is to set it to a function on the root View in your app that writes the new parameters to state (or to your flux/redux stores if you use that).
You can then pass that information through your app and use it as you see fit.

OpenLayers: Zoomable WMS overlay?

I have a problem with WMS overlays in OpenLayers. Basically I just want to add data from a WMS server as an overlay and not as a base layer. This appears to be a very simple problem but I am unable to find a solution. If I set singleTile to true, the overlays appears over the whole map but you cannot zoom in. If it is set to false, only one tile is displayed at every zoom level. If I set it as a base layer, it works just fine but I really want the overlay solution so I can make it transparent and see the map behind it.
Demonstration of the problem, with a different dataset but the issue is the same:
http://jsfiddle.net/adbnC/2/
I think it might be related to some coordinate system issues but I am no expert so any help is appreciated.
Thanks a lot!
Here is the relevant section of the code that does not work as expected:
var pop_layer = new OpenLayers.Layer.WMS("Population Density in 2000",
"http://sedac.ciesin.columbia.edu/geoserver/ows", {
layers: 'gpw-v3:gpw-v3-population-density_2000',
transparent: true
}, {
opacity: 0.5,
isBaseLayer: false,
// Setting single tile to true will kind of work but than one
// cannot zoom in any more.
singleTile: false
}
);
I can't quite get what exactly is wrong here, but I think it has something to do with messed up reference systems. Here is a workaround:
Modified Jsfiddle.net
I changed the map projection to spherical mercator and now it seems to work fine for me:
var mapOptions = {
div: "map",
projection: new OpenLayers.Projection("EPSG:900913"),
units: "m"
};
map = new OpenLayers.Map('map', mapOptions);
var osm = new OpenLayers.Layer.OSM();
map.addLayer(osm);
var pop_layer = new OpenLayers.Layer.WMS("Population Density in 2000", "http://sedac.ciesin.columbia.edu/geoserver/ows", {
layers: 'gpw-v3:gpw-v3-population-density_2000',
transparent: true
}, {
opacity: 0.5,
isBaseLayer: false
});
map.addLayer(osm);
map.addLayer(pop_layer);
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.setCenter(new OpenLayers.LonLat(0, 0), 2);​
Let me know if that helped!

Resources