Реализация OpenLayers "Геолокация с ориентацией" пример с Ionic 3 - PullRequest
0 голосов
/ 05 марта 2019

Я пытаюсь реализовать пример 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 нет ошибок, поэтому мне не с чем работать.

Есть предложения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...