根据半径向用户显示附近的位置

Posted

技术标签:

【中文标题】根据半径向用户显示附近的位置【英文标题】:Showing users nearby locations based off radius 【发布时间】:2021-08-06 07:35:00 【问题描述】:

我正在构建一个向用户显示最近位置的谷歌地图。我现在有一个 json 文件,但稍后将与数据库一起使用。我需要根据一定的半径向用户显示位置。下面是一个试图实现这一目标的组件。当我 setState 它只捕获数组中的最后一个元素。我不知道为什么。

        Geocode.setApiKey("apikey");
        Geocode.setLocationType("ROOFTOP");
        const distances = [
          
            value: 50,
            label: "50",
          ,
          
            value: 150,
            label: "150",
          ,
          
            value: 250,
            label: "250",
          ,
          
            value: 500,
            label: "500",
          ,
        ];
        
        //Gathers location and calculates distances then sets state of that distance
        
function Map() 
          const classes = useStyles();
        // sets state
          const [selected, setSelected] = useState();
          const [center] = useState( lat: 43.211243, lng: -112.413304 );
          const [userLocation, setUserLocation] = useState();
          const [input, setInput] = useState("");
          const [nearestPlace, setNearestPlace] = useState([]);
          const [miles, setMiles] = React.useState(50);
        
            // gets user location
          useEffect(() => 
            geocode();
          , []);
          // Grabs users location
          const geocode = async () => 
            let location = input;
            await axios
              .get("https://maps.googleapis.com/maps/api/geocode/json", 
                params: 
                  address: location,
                  key: "apikey",
                ,
              )
              .then((response) => 
                const  lat, lng  = response.data.results[0].geometry.location;
                setUserLocation( lat, lng ); // sets user location
              )
              .catch((error) => 
                console.log(error);
              );
          ;
    //calculation of lat and lng
          function distance(lat1, lng1, lat2, lng2, miles)  
            // miles optional
            if (typeof miles === "undefined") 
              miles = false;
            
            function deg2rad(deg) 
              return deg * (Math.PI / 180);
            
            function square(x) 
              return Math.pow(x, 2);
            
            var r = 6371; // radius of the earth in km
            lat1 = deg2rad(lat1);
            lat2 = deg2rad(lat2);
            var lat_dif = lat2 - lat1;
            var lng_dif = deg2rad(lng2 - lng1);
            var a =
              square(Math.sin(lat_dif / 2)) +
              Math.cos(lat1) * Math.cos(lat2) * square(Math.sin(lng_dif / 2));
            var d = 2 * r * Math.asin(Math.sqrt(a));
            if (miles) 
              return d * 0.621371;
             //return miles
            else 
              return d;
             //return km
          
        // this is where I get tripped up. Its not working properly

          const handleSubmit = (e) => 
            e.preventDefault();
            geocode();
            let nearest = [];
            for (let i = 0; i < locations.length; i++) 
              nearest.push(
                distance(
                  userLocation.lat,
                  userLocation.lng,
                  locations[i].location.lat,
                  locations[i].location.lng,
                  "miles"
                )
              );
            
            const result = nearest.map((item) => 
              let closest = [];
              if ((miles === "50" && item <= 50) || item <= 100) 
                closest.push(item);
                return closest;
              
            );
        
            result.forEach((el) => 
              if (el === "undefined") 
                return;
               else 
                 console.log(el) // this provides the correct values
                setNearestPlace(el); // Here is where it wont set my state to the values
                console.log(nearestPlace);
              
              return el;
            );
          ;
        
          const onSelect = (item) => 
            setSelected(item);
          ;
          const handleChange = (event) => 
            setMiles(event.target.value);
          ;
        
          return (
            <>
              <LoadScript googleMapsApiKey="apikey">
                <GoogleMap
                  className=classes.map
                  mapContainerStyle=mapStyles
                  zoom=7
                  center=center
                >
                  locations.map((item) => 
                    return (
                      <Marker
                        key=item.name
                        position=item.location
                        onClick=() => onSelect(item)
                      />
                    );
                  )
        
                  selected.location && (
                    <InfoWindow
                      position=selected.location
                      clickable=true
                      onCloseClick=() => setSelected()
                    >
                      <div>
                        selected.image ? (
                          <img
                            
                            style= width: "200px" 
                            src=selected.image
                          />
                        ) : null
                        <p>selected.name</p>
                        <p>selected.address</p>
                        <p>selected.phone</p>
                      </div>
                    </InfoWindow>
                  )
                </GoogleMap>
              </LoadScript>
              <div className=classes.formControl>
                <form
                  className=classes.form
                  onSubmit=handleSubmit
                  autoComplete="on"
                >
                  <div>
                    <TextField
                      className=classes.input
                      onChange=(e) => setInput(e.target.value)
                      value=input
                      size="small"
                      id="outlined-basic"
                      variant="outlined"
                      InputProps=
                        endAdornment: (
                          <InputAdornment position="end">
                            <SearchIcon className=classes.searchIcon />
                          </InputAdornment>
                        ),
                      
                    />
                  </div>
                </form>
                <div>
                  <Select
                    native
                    value=miles
                    onChange=handleChange
                    label="Age"
                    inputProps=
                      name: "miles",
                      id: "outlined-age-native-simple",
                    
                  >
                    <option aria-label="None" value="" />
                    <option value=50>50</option>
                    <option value=100>100</option>
                    <option value=150>150</option>
                    <option value=200>200</option>
                    <option value=250>250</option>
                    <option value=500>500</option>
                  </Select>
                </div>
              </div>
            </>
          );
        
        
        export default Map;
        
        

【问题讨论】:

【参考方案1】:

在这里

result.forEach((el) => 
  if (el === "undefined") 
    return;
   else 
    console.log(el) // this provides the correct values
    setNearestPlace(el); // Here is where it wont set my state to the values
    console.log(nearestPlace);
  
  return el;
);

您在循环中调用setNearestPlace() 并将数组元素作为参数传递。结果,传递的最后一个值,即数组的最后一个元素将是您的最终状态。

我相信你正在尝试做这样的事情

setNearestPlace(result.filter(ele => Boolean(ele))); // Boolean(ele) check whether the ele is null or undefined.

【讨论】:

以上是关于根据半径向用户显示附近的位置的主要内容,如果未能解决你的问题,请参考以下文章

找到给定半径内的附近位置

地理位置代码获取附近的城市

地理位置计算:如果点在半径内,则计算它们

MySQL:多个纬度和经度的附近位置

显示用户在PHP中当前位置的10公里半径范围内的用户

从数据库中搜索附近的地方 [swift]