I have the following code that takes the user's location from a google api, the detail I have is that the accuracy is too high, for example accuracy: 2600.670416166183, I don't know if someone knows how to solve this error, it would be very useful
const useGeoLocation = () => {
const [location, setLocation] = useState({
loaded: true,
coordinates: {
lat: "",
lng: "",
},
aceptacion: null,
});
const onSuccess = (location) => {
console.log(location);
setLocation({
loaded: true,
coordinates: {
lat: resultado.location.lat,
lng: resultado.location.lng,
},
aceptacion:1
});
};
useEffect(() => {
const url = `https://www.googleapis.com/geolocation/v1/geolocate?key=......`;
const http = new XMLHttpRequest();
http.open("POST", url);
http.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
let resultado = JSON.parse(this.responseText);
let latitude = resultado.location.lat;
let longitude = resultado.location.lng;
setLocation({
loaded: true,
coordinates: {
lat: resultado.location.lat,
lng: resultado.location.lng,
},
aceptacion:1
});
console.log(resultado);
return resultado
}
}
http.send();
}, []);
return location;
}; export default useGeoLocation;
I think you are using the wrong API for your needs.
Google Geolocation API is used to get location from Wifi/Bluetooth/Cell Tower/IP informations. In your example you don't put any additional information in the body of your request, so google will only give geolocation based on the user's IP, which doesn't have a good accuracy.
If you want a better accuracy using this API, you have to provides Wifi or Bluetooth spots near the user (see documentation here), but I don't think that's what you want, so I think the best solution is to use navigator.geolocation.getCurrentPosition native function from all browsers, it will get location directly from the device (GPS/Wifi/Bluetooth) like there :
https://developers.google.com/maps/documentation/geolocation/overview
You can find examples here :
How do I get user's location via navigator.geolocation before my fetch executes in componentDidMount() in react.js?
How to get location information in react?
Related
In my app, a user may want to run from point A to Point B, so we show them the route on a map.
The user plugs in their start location, it's sent to the server, and then spit out on the map on the following page (once they've started running.)
When trying to show them their route on the map, I keep getting the above warning for the info associated with the runner's destination.
The console logs it as:
object{
latitude: -1,
longitude: -1,
}
When I hard code coordinates into the function, the console logs the correct latitude and longitude, but it still does not spit it out on the map. Below is some of my code:
const [user_latitude, setUserLatitude] = useState(0)
const [user_longitude, setUserLongitude] = useState(0)
const [ startRun, setStartRun] = useState(null)
const [ endRun setEndRun ] = useState(null)
useFocusEffect(
React.useCallback(()=?{
let isActive = true;
const fetchGeoPosition = () =>{ //gets runner's current position
navigator.geolocation.getCurrentPosition(
position=>{
if(isActive){
setUserLatitude(position.coords.latitude)
setUserLongitude(position.coords.longitude)
}
...
const finalLocation = async()=>{
let running_response = await client_instance.get_final_locations
setEndRun({ //this spits out -1,-1 when pulled from server
latitude: client_response["location_info"]["end_lat"],
longitude: client_response["location_info"][end_lon"],
})
}
...
finalLocation()
setStartRun(
{
latitude: user_latitude,
longitude: user_longitude
},
)
...
<MapViewDirections
origin={startRun}
destination={endRun}
strokeWidth={5}
/>
<Marker coordinate={startRun}/> //This will render their start pin
<Marker coordinate={endRun}/> //This renders -1,-1 when imported from server
I ran into a similar problem and after some googling I discovered the reason for that error was because I was trying to get "directions from one island to another" (In my case, my origin coordinates was in Nigeria and the destination coordinates was in Australia). After changing my origin to the same country, I started getting directions.
You can refer to this page for some more clarity
I try to inject position changes to an JS/REACT-Application. The Application registering at window.navigator.geolocation.watchPosition. My idea is to stub the "watchPosition" method to get a handle on the callback function. Then calling the callback function from the application directly.
Like:
const watchPositionFake = (successCallback, errorCallback, options) => {
console.debug("PROXY set callback watchPosition");
originalWatchPositionSuccessCallback = successCallback;
};
cy.visit("/", {
onBeforeLoad(win) {
cy.stub(win.navigator.geolocation, "watchPosition").callsFake(watchPositionFake);
}
});
This doesn't work with function registering in the Application on the watchPosition. But this does work with function in the cypress-step file. (Working as in in the console.log I see changes in position according to the values I send in via originalWatchPositionSuccessCallback ).
Any idea who to fake a position change?
There is a different way to solve the issue of getting the callbacks of the registered function to navigator.geolocation.watchPosition triggered. The code in the question tried to solve this by cy.stub(win.navigator.geolocation, "watchPosition"), but this turned to be not working reliably (too soon, too late, different browser/window context, another iframe, ...), the precise reason varied.
An alternative solution to trigger the registered watchPosition callbacks without modifying the production code is the undocumented cypress (v6.2) automation interface in cypress to CDP.
export const setFakePosition = position => {
// https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-setGeolocationOverride
console.debug(`cypress::setGeolocationOverride with position ${JSON.stringify(position)}`);
cy.log("**setGeolocationOverride**").then(() =>
Cypress.automation("remote:debugger:protocol", {
command: "Emulation.setGeolocationOverride",
params: {
latitude: position.latitude,
longitude: position.longitude,
accuracy: 50
}
})
);
};
And verifying with:
let positionLogSpy;
When("vehicle is located in {string}", city => {
const position = cityLocationMap[city];
cy.window()
.then(win => {
const expectedLogMessage = `new position lat: ${position.latitude}, lng: ${position.longitude}`;
positionLogSpy = cy.spy(win.console, "log").withArgs(expectedLogMessage);
})
.then(() => {
setFakePosition(position);
});
});
Then("vehicle has moved to {string}", () => {
expect(positionLogSpy).to.be.called;
});
hello i have a server side method i am calling this method from client side.the method works fine.but when i return my query result.then it does not show in client side. but when i return something like 'hello' then it shows in client side. the issue is that my query is taking long time to execute. if anyone have idea to get response of query in my client side code.below i added my code.
Meteor.methods({
getResponseFromServer:function(latlong){
lng = parseFloat(latlong.lng);
lat = parseFloat(latlong.lat);
//return 'hello';
//this hello i got in my client side code.
console.log(Centers.find({ coordinates: { $near: { $geometry: { type: "Point", coordinates: [lat,lng] }, $maxDistance: 10000 } } }).fetch());
//getting data from server
var getObject = Centers.find({ coordinates: { $near: { $geometry: { type: "Point", coordinates: [lat,lng] }, $maxDistance: 10000 } } }).fetch();
//getting data from server and store it in an object and return it
return getObject;
}
});
and i have my client side code simple.
Template.searchlist.onRendered(function(){
this.searchedString = Router.current().params.name;
searchedParams = this.searchedString;
searchedParams = searchedParams.split('-');
var lat = searchedParams.pop();
var lng = searchedParams.pop(1);
lng = Number(lng).toFixed(6);
console.log(lng);
lat = Number(lat).toFixed(6);
var latlong = {'lat':lat,'lng':lng};
Meteor.call("getResponseFromServer",latlong,function(error,success){
console.log(error+' see sucess here');
console.log(success+' see failure here');
});
});
please give me solution about it if anyone have idea.
I'm building a google maps app with React.js.
My instinct is to create separate file with an ES6 class to handle search queries - within the class there will be a function that returns the search result. I intend to call that function from within a React Component.
See the component below for reference.
Should I move the code inside the findRoutes() and drawBoxes() methods to separate files? This is my first react app - want to learn how to best organize the code. Any tips are hugely appreciated.
var MapControl = React.createClass({
getInitialState: function(){
return {
originId: '',
destinationId: '',
radius: 1,
search: '',
map: {},
travelMode: google.maps.TravelMode.DRIVING
}
},
handleFormSubmit: function(input){
// Form Input
// Call findRoutes() once setState is complete.
this.setState({
originId: input.originId,
destinationId: input.destinationId,
radius: input.radius,
search: input.search
}, this.findRoutes);
},
handleMapRender: function(map){
// Intialized Google Map
this.setState({map: map});
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
routeBoxer = new RouteBoxer();
directionsDisplay.setMap(map);
placesService = new google.maps.places.PlacesService(map);
},
findRoutes: function(){
var me = this;
if (!this.state.originId || !this.state.destinationId) {
alert("findRoutes!");
return;
}
directionsService.route({
origin: {'placeId': this.state.originId},
destination: {'placeId': this.state.destinationId},
travelMode: this.state.travelMode
}, _.bind(function(response, status){
if (status === google.maps.DirectionsStatus.OK) {
// me.response = response;
directionsDisplay.setDirections(response);
var path = response.routes[0].overview_path;
this.setState({
routes: response,
boxes: routeBoxer.box(path, this.state.radius)
},this.drawBoxes);
} else {
window.alert('Directions config failed due to ' + status);
}
}, this));
},
drawBoxes: function(){
var boxpolys = new Array(this.state.boxes.length);
for (var i = 0; i < this.state.boxes.length; i++) {
boxpolys[i] = new google.maps.Rectangle({
bounds: this.state.boxes[i],
fillOpacity: 0,
strokeOpacity: 1.0,
strokeColor: '#000000',
strokeWeight: 1,
map: this.state.map
});
}
},
render: function() {
return (
<div className="MapControl">
<h1>Search</h1>
<MapForm
onFormSubmit={this.handleFormSubmit}
map={this.state.map}/>
<GMap
setMapState={this.handleMapRender}
originId= {this.state.originId}
destinationId= {this.state.destinationId}
radius= {this.state.radius}
search= {this.state.search}/>
</div>
);
}
});
Your instinct is correct, in general it's good practice to keep your view code as minimal as possible, and to move anything that is not explicitly related to rendering your view into another class.
React.js itself is not opinionated as to how you handle the rest of your application needs but a few libraries have emerged as the leading solutions for handling events, routing, services, data, etc.
You should review the Flux pattern for an overview of how you might manage the rest of your applications needs for React apps.
https://facebook.github.io/flux/docs/overview.html
I've moved on from Flux to using Redux recently
http://redux.js.org/ (which has emerged as the leading 'Fluxish' state management lib)
If you want to just get something up and running quickly and aren't trying to dive into all that just yet, I'd move the findRoutes method to an external service that you import in... drawBoxes seems fine to keep in here as it is directly related to rendering map elements in the view
I'm building Ionic application that have geolocation (Google Api), but that's irelevant, in upper right corner is button which i want to make to take screenshot and automatically make popover with options to send that screenshot image via email, viber..., but i don't have an idea how to take that screenshot, I googled and googled without any luck, please help.
app.controller('MapCtrl', function($scope, $cordovaGeolocation, $ionicLoading, $ionicPlatform) {
$ionicPlatform.ready(function() {
$ionicLoading.show({
template: '<ion-spinner icon="bubbles"></ion-spinner><br/>Acquiring location!'
});
var posOptions = {
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 0
};
$cordovaGeolocation.getCurrentPosition(posOptions).then(function (position) {
var lat = position.coords.latitude;
var long = position.coords.longitude;
var myLatlng = new google.maps.LatLng(lat, long);
var mapOptions = {
center: myLatlng,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
$scope.map = map;
$ionicLoading.hide();
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Lokacija'
});
}, function(err) {
$ionicLoading.hide();
console.log(err);
});
});
});
Two options, as far as I can tell:
Use a third-party Cordova plugin, such as https://github.com/gitawego/cordova-screenshot - this will most likely include the application's UI elements too, though, which might not be what you want.
Perhaps a better idea would be to use the Google Static Maps API - you can pass the current parameters from your dynamic map to it, and it'll return an image version.
This should get you started: How to take a screen shot in ionic
After you received the picture from the plugin, you can just use ionic's popover service to display it there.
This below code should help
*The function will take screenshot and share popup
For More details you can visit SocialSharing and Screenshot Ionic offical page
import { SocialSharing } from '#ionic-native/social-sharing/ngx';
import { Screenshot } from '#ionic-native/screenshot/ngx';
constructor(
private socialSharing: SocialSharing,
private screenshot: Screenshot
) { }
share(){
this.platform.ready().then(() => {
this.screenshot.URI(80)
.then((res) => {
//this.socialSharing.share('df',res.URI,null)
this.socialSharing.share('',null,res.URI,null)
.then(() => {},
() => {
alert('SocialSharing failed');
});
},
() => {
alert('Screenshot failed');
});
});
}