Wait until openlayers 5 geolocation returned a value

北慕城南 提交于 2020-01-05 05:26:26

问题


I am using openlayers 5 to implement a simple geolocation functionality :

When check the geolocation checkbox, the geolocation starts, zooms to the position with an animated transition and it automatically tracks the position constantly. It adds a feature in a vector layer.

When uncheck the geolocation checkbox, the geolocation is turned off, along with the tracking and that vector layer is cleared.

My problem is that I don't know how to wait until the geolocation has a value, so I can properly continue with the zooming in that position. I think is normal for geolocation to take a little time until it has a value, but I don't know how to wait until then. My code just zooms in its current position and after a while the geolocation point is rendered in the right place.

My code (openlayers 5 + angular 6)

ngOnInit(){ //while initializing everything else

    this.vectorlayer = new VectorLayer({
      source: this.vectorsource,
      style: styleFunction,
      title:'features'
    });

    this.geolocation = new Geolocation({      
      trackingOptions: {
        enableHighAccuracy: true
      },
      projection: 'EPSG:3857'
    });

    this.geolocation.on('error', (error) => {
      this.geolocationerror=true;
      this.geolocationmsg = error;
    });

    this.accuracyFeature = new Feature(); 
    this.geolocation.on('change:accuracyGeometry', ()=> {
      this.accuracyFeature.setGeometry(this.geolocation.getAccuracyGeometry());
    });

    this.positionFeature = new Feature();
    this.positionFeature.setStyle(new Style({
      image: new CircleStyle({
        radius: 6,
        fill: new Fill({
          color: '#3399CC'
        }),
        stroke: new Stroke({
          color: '#fff',
          width: 2
        })
      })
    }));

    this.geolocation.on('change:position', ()=> {
      let coordinates = this.geolocation.getPosition();
      this.positionFeature.setGeometry(coordinates ?
        new Point(coordinates) : null);
    });

    if(window.innerWidth < 600){
      this.isChecked = true;
    }    

    this.geolocsource = new VectorSource({});

    this.geoloclayer = new VectorLayer({
      source: this.geolocsource,
      title:'location'
    });

    this.view = new View({ ....
    this.olmap = new Map({....

   //turn on in smaller screenc, <600
   this.toggleGeolocation(this.isChecked);

}//ngOnInit

outside the ngOnInit

  toggleGeolocation(checked){    
    this.geolocationmsg='';
    this.geolocationerror=false;
    if(checked){   //turned on                                    
      this.geolocation.setTracking(checked);
      this.geolocsource.addFeatures([this.accuracyFeature, this.positionFeature]);             
      this.geolocOn = true;   
      this.geolocLiveCoords = this.geolocation.getPosition();
      let center = this.geolocation.getPosition();      
      this.olmap.getView().animate({
        center: center,
        duration: 2000,
        zoom:10
      });   
    }
    else{   //turned off
      this.geolocation.setTracking(checked);      
      this.geolocOn = false;
      this.geolocsource.clear();
      this.geolocLiveCoords='';
    }    
  }

and the html part

<label for="track">track position<input id="trackpos" type="checkbox" [(ngModel)]="isChecked" (change)="toggleGeolocation(isChecked)"/></label>
<div  *ngIf='geolocationerror'>{{geolocationmsg}}</div>
<div  *ngIf='geolocOn'>{{geolocLiveCoords}}</div>
<div id="map" class="map" tabindex="0"></div>

I also tried using promises

outside the ngOnInit, change toggleGeolocation

  getpos() {
    console.log('in');
    return new Promise(resolve => {      
     resolve(this.geolocation.getPosition());
    });
  }

  toggleGeolocation(checked){    
    this.geolocationmsg='';
    this.geolocationerror=false;
    if(checked){            
      this.getpos().then((value) => {        
        this.geolocsource.addFeatures([this.accuracyFeature, this.positionFeature]) ;   
        this.olmap.getView().animate({
          center: value,
          duration: 2000,
          zoom:10
        });
        this.geolocation.setTracking(checked);            
      });                              
    }
    else{
      this.geolocation.setTracking(checked);      
      this.geolocOn = false;
      this.geolocsource.clear();
      this.geolocLiveCoords='';
    }    
  }

The getpos is called (I can see the in on the console), but it never has a value, so it returns undefined .


回答1:


Excellent observation by @geocodezip. I had to change the toggleGeolocation and the this.geolocation.on('change:position' and it works.

A couple of things sometimes I click the geolocation, it gets the coords and then it gets them again, causeing the animation to be jerky and flicker as it goes. Any ideas?

I guess it should follow the movement, this is why the view animation should be in the this.geolocation.on('change:position'. But is this calculation-intensive, causing the map to be non-responsive if the user moves constantly?

Thanks

Now my whole code is

ngOnInit() {
this.geolocation = new Geolocation({      
      trackingOptions: {
        enableHighAccuracy: true
      },
      projection: 'EPSG:3857'
    });

    this.geolocation.on('error', (error) => {
      this.geolocationerror=true;
      this.geolocationmsg = error;
    });

    this.accuracyFeature = new Feature(); 
    this.geolocation.on('change:accuracyGeometry', ()=> {
      this.accuracyFeature.setGeometry(this.geolocation.getAccuracyGeometry());
    });

    this.positionFeature = new Feature();
    this.positionFeature.setStyle(new Style({
      image: new CircleStyle({
        radius: 6,
        fill: new Fill({
          color: '#3399CC'
        }),
        stroke: new Stroke({
          color: '#fff',
          width: 2
        })
      })
    }));

    this.geolocation.on('change:position', ()=> {
      console.log('in on chnage pos');
      let coordinates = this.geolocation.getPosition();
      console.log('coordinates > ',coordinates);
      this.positionFeature.setGeometry(coordinates ? new Point(coordinates) : null);
      this.geolocLiveCoords = coordinates;
      let center = coordinates;      
      this.olmap.getView().animate({
        center: center,
        duration: 2000,
        zoom:10
      }); 
    });

    if(window.innerWidth < 600){
      this.isChecked = true;
    }    

    this.geolocsource = new VectorSource({});

    this.geoloclayer = new VectorLayer({
      source: this.geolocsource,
      title:'location'
    });
    this.view = new View({  ....
    this.olmap = new Map({....
    this.toggleGeolocation(this.isChecked);

  }//ngOnInit

  toggleGeolocation(checked){    
    this.geolocationmsg='';
    this.geolocationerror=false;
    if(checked){                      
      this.geolocation.setTracking(checked);
      console.log('right before add features');
      this.geolocsource.addFeatures([this.accuracyFeature, this.positionFeature]);             
      this.geolocOn = true;   
    }
    else{
      this.geolocation.setTracking(checked);      
      this.geolocOn = false;
      this.geolocsource.clear();
      this.geolocLiveCoords='';
    }    
  }


来源:https://stackoverflow.com/questions/51726230/wait-until-openlayers-5-geolocation-returned-a-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!