我正在尝试在Ionic 3应用程序中从其GitHub页面(https://github.com/openlayers/openlayers/blob/master/examples/geolocation-orientation.js)实现OpenLayers“定向定位”示例。
基本上,我的问题是什么:在我的示例中,TileLayer的“ postrender”事件从未调用,因此我的位置永远不会显示在地图上。让我们展示一下代码:
因此,首先,导入所有必需的库:
import OlMap from 'ol/Map';
import OlXYZ from 'ol/source/XYZ';
import OlTileLayer from 'ol/layer/Tile';
import OlView from 'ol/View';
import OlOSM from 'ol/source/OSM';
import OlOverlay from 'ol/Overlay';
import OlLineString from 'ol/geom/LineString';
import { fromLonLat } from 'ol/proj';
import OlGeolocation from 'ol/Geolocation';
因此,接下来,我将使用Ionic的ionViewDidLoad()方法进行操作:
ionViewDidLoad()
{
// let myPosition = await this.getLocation();
this.view = new OlView({
center: fromLonLat([5.8713, 45.6452]),
zoom: 19
});
this.layer = new OlTileLayer({
source: new OlOSM()
});
this.map = new OlMap({
layers: [this.layer],
target: 'map',
view: this.view
});
this.markerEl = document.getElementById('geolocation_marker');
this.marker = new OlOverlay({
positioning: 'center-center',
element: this.markerEl,
stopEvent: false
});
// this.marker.setPosition(fromLonLat([myPosition.coords.longitude, myPosition.coords.latitude])); // sets marker just fine
this.map.addOverlay(this.marker);
// COPIED EXAMPLE
this.positions = new OlLineString([], 'XYZM');
// Geolocation Control
this.olgeolocation = new OlGeolocation({
projection: this.view.getProjection(),
trackingOptions: {
maximumAge: 10000,
enableHighAccuracy: true,
timeout: 600000
}
});
let self = this;
this.olgeolocation.on('change', function() {
console.log('Location changed');
const position = self.olgeolocation.getPosition();
const accuracy = self.olgeolocation.getAccuracy();
const heading = self.olgeolocation.getHeading() || 0;
const speed = self.olgeolocation.getSpeed() || 0;
const m = Date.now();
self.addPosition(position, heading, m, speed);
const coords = self.positions.getCoordinates();
const len = coords.length;
if (len >= 2) {
self.deltaMean = (coords[len - 1][3] - coords[0][3]) / (len - 1);
}
});
this.olgeolocation.on('error', function() {
alert('geolocation error');
});
this.olgeolocation.setTracking(true);
this.layer.on('postrender', this.updateView); // never called to updateView
this.map.render();
}
几乎一样,我只声明变量为类属性并使用它们。另外,还有一些其他方法,也只是从其示例中复制而来:
// modulo for negative values
private mod(n)
{
return ((n % (2 * Math.PI)) + (2 * Math.PI)) % (2 * Math.PI);
}
private addPosition(position, heading, m, speed)
{
console.log('Add Position called');
const x = position[0];
const y = position[1];
const fCoords = this.positions.getCoordinates();
const previous = fCoords[fCoords.length - 1];
const prevHeading = previous && previous[2];
if (prevHeading) {
let headingDiff = heading - this.mod(prevHeading);
// force the rotation change to be less than 180°
if (Math.abs(headingDiff) > Math.PI) {
const sign = (headingDiff >= 0) ? 1 : -1;
headingDiff = -sign * (2 * Math.PI - Math.abs(headingDiff));
}
heading = prevHeading + headingDiff;
}
this.positions.appendCoordinate([x, y, heading, m]);
// only keep the 20 last coordinates
this.positions.setCoordinates(this.positions.getCoordinates().slice(-20));
if (heading && speed) {
this.markerEl.src = 'https://raw.githubusercontent.com/openlayers/openlayers/master/examples/data/geolocation_marker_heading.png';
} else {
this.markerEl.src = 'https://raw.githubusercontent.com/openlayers/openlayers/master/examples/data/geolocation_marker.png';
}
}
// recenters the view by putting the given coordinates at 3/4 from the top or
// the screen
private getCenterWithHeading(position, rotation, resolution)
{
console.log('Get Center with Heading called');
const size = this.map.getSize();
const height = size[1];
return [
position[0] - Math.sin(rotation) * height * resolution * 1 / 4,
position[1] + Math.cos(rotation) * height * resolution * 1 / 4
];
}
private previousM = 0;
private updateView()
{
console.log('Update View Called');
// use sampling period to get a smooth transition
let m = Date.now() - this.deltaMean * 1.5;
m = Math.max(m, this.previousM);
this.previousM = m;
// interpolate position along positions LineString
const c = this.positions.getCoordinateAtM(m, true);
if (c) {
this.view.setCenter(this.getCenterWithHeading(c, -c[2], this.view.getResolution()));
this.view.setRotation(-c[2]);
this.marker.setPosition(c);
}
}
就是这样;我的位置已成功检索,这也是正确的,如果我直接在地图上设置标记,它也会显示-但是,如果我这样做,则永远不会调用updateView方法,并且应在TileLayer的事件“ postrender”时调用'被触发-但这永远不会发生。
在浏览器中对其进行了测试,在模拟器(Android,iOS)上进行了测试,在实际的Android设备上进行了测试,这是相同的。当然,DevTools控制台中没有错误,因此我基本上没有任何工作。
有什么建议吗?