使用Ionic 3实施OpenLayers“定向定位”示例

时间:2019-03-05 09:42:38

标签: typescript ionic3 openlayers

我正在尝试在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控制台中没有错误,因此我基本上没有任何工作。

有什么建议吗?

0 个答案:

没有答案