Changing animateCamera pitch and zoom properties dynamically doesn't work - reactjs

Changing animateCamera pitch and zoom properties dynamically with useState doesn't work
onLayout={() => {
map.current.animateCamera({
center: { latitude: location?.coords?.latitude, longitude: location?.coords?.longitude },
zoom: zoomLevel,
heading: 50,
pitch: pitchLevel,
altitude: 5,
})
}}
I find that onlayout doesn't quite work with transformations.
So here's all of the undocumented or buggy behavior I've encountered with onLayout and .measure so far:
onLayout doesn't get called in some conditions (seemingly when an element is moved by a parent resizing)
the measure returns undefined on android unless there's an onLayout or collapsible: false on the view
onLayout doesn't take transforms into account, it returns the "internal" size of the view not the size displayed on the screen
onLayout doesn't fire for animations of transforms (which is pretty much all animations since only transforms and opacity can use native driver) -- that's this issue
measure returns different values for width and height than onLayout. It returns scaled values if any parent is scaled as opposed to the raw values. Docs suggest the opposite.
onLayout Will return wrong/random values during component mount in some (maybe all?) cases if the view or any parent is being animated.
It's because layout process is not involved in transformations at all. Actually Animated can't change any properties that can change layout of the component tree.
I find this approach https://reactnative.dev/docs/direct-manipulation
I will give a snippet if I find solution

I think you should use hook (useEffect) for animating Map to then region. In my case i was getting new locations from GoogleAutoPlaces
api . i am receiving latlng object in coordinate variable. here you
can add coordinate variable as dependency and when your location
will change it will automatically animate the map to the new
location. useEffect(() => { mapref?.current?.animateToRegion(coordinate, 1000); }, [coordinate]);

solution was:
ref={(current) => (map.current = current)}
onUserLocationChange={() => {
map.current.animateCamera({
center: {
latitude: locationUpdate?.coords?.latitude,
longitude: locationUpdate?.coords?.longitude,
},
zoom: 16,
heading: Math.round(headingRef.current),
pitch: 90,
altitude: Math.round(altitudeRef.current),
useNativeDriver: true,
});
}}
although to even enhance react native performance you can set this in useCallback hook and call it from that like:
onUserLocationChange={animateCameraUseCallback}

Related

How to change the stroke color of a polygon onMouseEnter in React Google Map API

I am having an array of polygon coordinates which are being mapped and displayed on the map.
Secondly, I have a mouseenter and mouseout event which takes in the particular lat and lng coordinate of a particular polygon and zooms over them to focus on them.
Now what I want to achieve is that, anytime I mouse over any polygon from the list on the table, I want the strokeColor of that particular polygon to change. My current logic only changes the strokeColor of every polygon, which is not what I want.
My code is explained below:
This is the mouse-enter function
const handleRowHover = (event, props) => {
console.log("event", event);
console.log("props", props);
setCenter({
lat: props?.data?.geoData?.point?.coordinates?.[1],
lng: props?.data?.geoData?.point?.coordinates?.[0],
});
setZoomLevel(18);
setMapColor("red");
};
This is the mapped list of polygons from an API endpoint
{allFarmsPolygons.map((poly) => (
<Polygon paths={poly} options={options} />
))}
This is the react google maps api options
const options = {
fillColor: "rgb(128,128,128, 0.5)",
fillOpacity: 1,
strokeColor: center ? mapColor : "#066344",
strokeOpacity: 10,
strokeWeight: 2,
clickable: true,
draggable: false,
editable: false,
geodesic: false,
zIndex: 2,
};
Please any help or hint would be much appreciated. If additional info is needed, I can provide them.
I have tried putting the strokeColor into state, but it just applies to every polygon on the iteration. I want it to apply to only the particular polygon being mouse entered. I am using material-table to display the names of each polygon by the way.

Duplicate image shown - useEffect issue?

I have some code to display my board as shown below:
<Grid item xs={6} justify="center">
<Paper id="board">
</Paper>
</Grid>
But sometimes when I save my code, it displays a duplicate board on the screen on localhost:3000, although not always. Example below:
I am suspecting it it might have something to do with my useEffect:
useEffect(() => {
// componentDidMount() {
const board = new Gameboard(document.getElementById('board'), {
// position: 'r4r1k/p1P1qppp/1p6/8/5B2/2Q1P3/P4PPP/R3KB1R b KQ - 0 21',
position: game.fen(),
sprite: {
url: './gameboard-sprite.svg', // pieces and markers are stored as svg in the sprite
grid: 40, // the sprite is tiled with one piece every 40px
cache: true,
},
orientation: COLOR.white,
moveInputMode: MOVE_INPUT_MODE.dragPiece,
responsive: true,
});
board.enableMoveInput(inputHandler);
}, []);
Any idea why it could be displaying twice, but only sometimes? It always removes the duplicate board when I click the browser refresh button if that helps. But it is often there when I first save my code.
Save your Gameboard instance in useRef, this way only one instance is created:
const board = useRef();
useEffect(() => {
if(!board.current) {
board.current = new Gameboard(document.getElementById('board'), {
// position: 'r4r1k/p1P1qppp/1p6/8/5B2/2Q1P3/P4PPP/R3KB1R b KQ - 0 21',
position: game.fen(),
sprite: {
url: './gameboard-sprite.svg', // pieces and markers are stored as svg in the sprite
grid: 40, // the sprite is tiled with one piece every 40px
cache: true,
},
orientation: COLOR.white,
moveInputMode: MOVE_INPUT_MODE.dragPiece,
responsive: true,
});
board.current.enableMoveInput(inputHandler);
}
}, []);
You need to return cleanup function from effect, so when fast refresh will rerun it, there will be no duplicates. It works properly sometimes because sometimes fast refresh sometimes don't try to preserve state and renders everything as new. This depends on changes you made, so when you change one file it will render clean, but on another files it will try to preserve state and only rerun effects (this is where second board added).
Also, it is better not to interact with DOM directly and use ref instead. This is better way to work with DOM in react, since it's react main purpose to update DOM.

Is it possible to display mapbox coordinates inside a dynamic url?

I'm working on a mapbox app and I need to make a dynamic URL to reflect mapbox info like lat, long and zoom level.
ex: /?city=London&zoom=1&lat=30&lng=140. On page load map should be centred and zoomed accordingly. How to read/write page URL?
Just activate the hash : true in the Map initial settings
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/outdoors-v11',
center: [128, 47],
zoom: 16.5,
pitch: 60,
hash: true // just add this
});
It’s not the same param names but you’ll have the same information

How to get lat lang of top left and bottom right of map when zoomed

I am trying to get top left and right bottom of the Map which i am displaying. And i am trying to get this particular data in zoom event, but somehow this.map is becoming undefined and breaking the application
this.map.on('zoomend', function (layer) {
console.log("zoom",layer.target._zoom)
console.log("getbounds", this.map.getBounds());
});
Below i am providing the componentDidMount, here only i am defining zoom event, which working fine if i simply console.
componentDidMount() {
/* We are loading the map here whether or not load has loaded */
this.map = L.map('map', {
center: [50, 10],
zoom: 3,
minZoom: 2,
maxZoom: 11,
zoomControl: false,
attributionControl: false,
scrollwheel: false,
legends: true,
infoControl: false,
});
console.log("getbounds", this.map.getBounds()); //WORKING BUT JUST ONCE, when this component mounts.
this.map.on('zoomend', function (layer,a) {
console.log("zoom",layer.target._zoom)
console.log("zoom",layer)
console.log("a",a)
console.log("getbounds", this.map.getBounds()); // NOT WORKING, this.map GETS UNDEFINED which is obvious also.
});
/* Giving zoom control a different place in UI */
L.control.zoom({ position: 'topright' }).addTo(this.map);
L.control.scale({ position: "topright" }).addTo(this.map);
/* Selecting and showing styles for the map */
L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {
}).addTo(this.map);
}
Just change this part of your code bro
this.map.on('zoomend', (layer,a) => {
console.log("zoom",layer.target._zoom)
console.log("zoom",layer)
console.log("a",a)
console.log("getbounds", this.map.getBounds()); // NOT WORKING, this.map GETS UNDEFINED which is obvious also.
});
The reason why your code did not work is you were using simple function as a callback which need to bind to use this.
Solution: Use arrow function

Why panning google map updates angularjs scope var?

Kind of an odd question/hard to find an answer. I'm relatively new to using angularjs and have a problem i'm confused about.
I've set up a google map using http://angular-ui.github.io/angular-google-maps/#!/ and have an issue.
So i have a $scope.homeBase where i am setting a lat & long for the owners 'Home Base', i want to use that location to set the on load map center, & a pin to show the location. So in my mind cool, set the one var and use it in both locations. Wrong.
So this works on load, but every time i pan the map, i guess it re-sets the map center location, which in turn binds to the map marker and sends the marker to the middle of the screen, on every pan.
Is there anyway to have the two not bound? or have separate vars? without them bound?
i thought a simple 'var homebase' would remove binding and not update the var. instead of using scope but it still binds?
This perhaps is a newb question but i appreciate any pointing in proper direction.
Thanks again
here's my code.
// uiGmapGoogleMapApi is a promise, The "then" callback function provides a maps object.
uiGmapGoogleMapApi.then(function() {
// Setting homebase coords, these will come from firebase
$scope.homeBase = { latitude: -34.18405, longitude: 150.71319 };
// Set default map.
$scope.map = {
center: $scope.homeBase,
pan: true,
zoom: 14,
events: {
click: function(){
}
}
};
// Set homebase marker.
$scope.homebaseMarker = {
id: 0,
coords: $scope.homeBase,
options: { draggable: false },
};
});
I was able to set the center on page load via
angular.copy(var)

Resources