Я пытаюсь реализовать пример OpenLayers "Геолокация с ориентацией" со страницы GitHub (https://github.com/openlayers/openlayers/blob/master/examples/geolocation-orientation.js) в моем приложении Ionic 3.
В принципе, в чем моя проблема: "postrender")событие для TileLayer никогда не вызывается в моем примере, поэтому мое местоположение никогда не отображается на карте. Давайте покажем код:
Итак, сначала импортируем все необходимые библиотеки:
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 нет ошибок, поэтому мне не с чем работать.
Есть предложения?