NGX-OpenLayer 缩放以显示所有测试点



在我们的 Angular 5 项目中,我们包含一个带有 ngx-openlayer 的 openstreetmap。 我有一张带有 POI 列表的地图。此列表可以按不同的条件进行筛选。我想更改缩放级别,以便显示列表中的所有 POI。

正如我发现我们可以使用

this.map.instance.getView().fit(extent1, this.map.instance.getSize());

这样做,但我有问题要获得正确的程度。

<aol-map #map [width]="'100%'" [height]="'100%'">
<aol-control-defaults></aol-control-defaults>
<aol-control-scaleline></aol-control-scaleline>
<aol-interaction-default></aol-interaction-default>
<aol-interaction-select (onSelect)="onClick($event)"></aol-interaction-select>
<aol-view #view [zoom]="zoom">
<aol-coordinate [x]="centerlong" [y]="centerlat" [srid]="'EPSG:4326'"></aol-coordinate>
</aol-view>
<!-- aol-layer-tile  [postcompose]="onPostcompose" -->
<aol-layer-tile>
<aol-source-osm></aol-source-osm>
</aol-layer-tile>
<!-- List of POIs  --> 
<aol-layer-vector [opacity]="1" (click)="onClick('Layer')">
<aol-source-vector #source>
<ng-container *ngFor="let item of api.datapoints">
<aol-feature *ngIf="item.icon" [id]="item.uuid">
<aol-geometry-point>
<aol-coordinate [x]="item.longitude" [y]="item.latitude" [srid]="'EPSG:4326'"></aol-coordinate>
</aol-geometry-point>
<aol-style>
<aol-style-icon [src]="'./assets/img/'+item.icon" [anchor]="[0.5, 1]" [anchorXUnits]="'fraction'"
[anchorYUnits]="'fraction'" [scale]="1" [anchorOrigin]="'top-left'"></aol-style-icon>
</aol-style>
</aol-feature>
</ng-container>
</aol-source-vector>
</aol-layer-vector>
<aol-overlay *ngIf="this.api.datapoints.length == 0">
<aol-coordinate
[x]="centerlong"
[y]="centerlat"
[srid]="'EPSG:4326'"
>
</aol-coordinate>
<aol-content>
<div class="alert alert-danger" i18n>No data points found!</div>
</aol-content>
</aol-overlay>
</aol-map>

在打字稿上,我尝试在源(extent1)上获得所需的范围,但它给了我从-无穷大到无穷大的范围。我也尝试从我的同事那里获得minX,maxX,minY和maxY。(范围)这将深入缩放到中心。我认为这是我需要将我们的坐标从 EPSG:4326 转换为一些内部坐标的问题。但是我该怎么做呢?

import {Component, OnInit, ViewChild} from '@angular/core';
import {ApiGatewayService} from '../../../service/apigateway.service';
@Component({
selector: 'app-data-map',
templateUrl: './data-map.component.html',
styleUrls: ['./data-map.component.css']
})
export class DataMapComponent implements OnInit {
@ViewChild('view') view: any;
@ViewChild('map') map: any;
@ViewChild('source') source: any;
centerlong = 14.8;
centerlat = 52.50;
zoom = 7;

constructor(public api: ApiGatewayService) {
}

ngOnInit() {
console.log('MAP', this.view);
}
updateZoom() {
if (this.api.datapoints.length > 1) {
console.log("updateZoom")
let minlong = 200;
let maxlong = -200;
let minlat = 100;
let maxlat = -100;
for (const item of this.api.datapoints) {
console.log('Item', item);
if (item.latitude < minlat) {
minlat = item.latitude;
}
if (item.latitude > maxlat) {
maxlat = item.latitude;
}
if (item.longitude < minlong) {
minlong = item.longitude;
}
if (item.longitude > maxlong) {
maxlong = item.longitude;
}
console.log('Box', minlat, minlong, maxlat, maxlong);
}
this.centerlong = (minlong + maxlong) / 2;
this.centerlat = (minlat + maxlat) / 2;
const extent = [minlong, minlat, maxlong, maxlat];
if (this.map.instance) {
var extent1 = this.source.instance.getExtent();
console.log('Set zoom level', extent1);
this.map.instance.getView().fit(extent1,
this.map.instance.getSize());
}
}
}
}

看起来我需要ol.proj.transformExtent()。 但是我怎样才能从ngx-openlayer访问ol.proj呢? 目的地系统是什么才能进行转换?

我想我已经找到了解决方案。

首先 ngx-openlayer 依赖于 openlayer,所以我们也可以直接导入 openlayer:

import {proj} from 'openlayers';

所以现在我们可以在需要调用 ol.proj 时调用 proj。

Openstreetmap使用的投影是EPSG:3857。 为了将我的程度转移到这个协调系统,我现在将调用

const extent1 = proj.transformExtent(extent, 'EPSG:4326', 'EPSG:3857'); 

整个打字稿作为参考:

import {AfterViewInit, Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {MapEvent, proj} from 'openlayers';
import {Subscription} from 'rxjs';
import {ApiGatewayService} from '../../../service/apigateway.service';

@Component({
selector: 'app-data-map',
templateUrl: './data-map.component.html',
styleUrls: ['./data-map.component.css']
})
export class DataMapComponent implements OnInit, OnDestroy, AfterViewInit {
subscription: Subscription;
@ViewChild('map', {static: true}) map: any;
centerlong = 10.447683;
centerlat = 51.163375;
datapoints = [];
tempZoom = 0;
zoom = 7;

constructor(public api: ApiGatewayService) {
}
ngOnInit() {
this.subscription = this.api.datapointsChanged
.subscribe(item => {
console.log('DataMapComponent::DatapointsChanged', item);
this.datapoints = this.api.datapoints;
this.updateZoom();
});
this.updateZoom();
}
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
onMoveEnd(e: MapEvent) {
console.log('DataMapComponent::onMoveEnd::getZoom' + e.map.getView().getZoom());
this.zoom = e.map.getView().getZoom();
if (this.tempZoom > 0) {
if (this.zoom > this.tempZoom) {
const zoom = this.tempZoom;
this.tempZoom = 0;
this.zoom = zoom;
}
}
}
updateZoom() {
console.log('DataMapComponent::updateZoom');
if (this.api.datapoints.length > 0) {
console.log('DataMapComponent::updateZoom::Lenght', this.api.datapoints.length);
let minlong = 200;
let maxlong = -200;
let minlat = 100;
let maxlat = -100;
for (const item of this.api.datapoints) {
if (this.useCoord(item.longitude, item.longitude)) {
if (item.latitude < minlat) {
minlat = item.latitude;
}
if (item.latitude > maxlat) {
maxlat = item.latitude;
}
if (item.longitude < minlong) {
minlong = item.longitude;
}
if (item.longitude > maxlong) {
maxlong = item.longitude;
}
}
}
this.centerlong = (minlong + maxlong) / 2;
this.centerlat = (minlat + maxlat) / 2;
if (this.map.instance) {
if (this.api.datapoints.length > 1) {
const extent: [number, number, number, number] = [minlong, minlat, maxlong, maxlat];
console.log('DataMapComponent::updateZoom::Extent1', extent);
console.log('DataMapComponent::updateZoom::Map', this.map.instance);
const extent1 = proj.transformExtent(extent, 'EPSG:4326', 'EPSG:3857');
// var extent1 = this.source.instance.getExtent();
console.log('DataMapComponent::updateZoom::Extent2', extent1);
this.map.instance.getView().fit(extent1, this.map.instance.getSize());
this.tempZoom = 10;
} else {
this.map.instance.getView().setCenter(proj.transform([this.centerlong, this.centerlat], 'EPSG:4326', 'EPSG:3857'));
this.zoom = 10;
}
} else {
console.log('DataMapComponent::updateZoom Map not ready!');
setTimeout(_ => {
this.updateZoom();
}, 200);
}
}
}
useCoord(lat, long): boolean {
const result = !Number.isNaN(Number(lat)) && !Number.isNaN(Number(long)) && (Number(lat) !== 0.0 || Number(long) !== 0.0);
// console.log('DataDetailJobComponent::useCoord::lat,long,result', lat, Number.isNaN(lat), long, Number.isNaN(long), result);
return result;
}
}

在 html 代码上,我们需要监听 MoveEnd 事件

<aol-map #map [width]="'100%'" [height]="'100%'" (onMoveEnd)="onMoveEnd($event)">
<aol-control-defaults > </aol-control-defaults>
<!-- [units]="'degrees', 'imperial', 'nautical', 'metric', 'us'" -->
<aol-control-scaleline></aol-control-scaleline>
<aol-interaction-default></aol-interaction-default>
<aol-view [zoom]="zoom" [maxZoom]="20">
<aol-coordinate [x]="centerlong" [y]="centerlat" [srid]="'EPSG:4326'"></aol-coordinate>
</aol-view>
<!-- aol-layer-tile  [postcompose]="onPostcompose" -->
<aol-layer-tile [zIndex]="1">
<aol-source-osm></aol-source-osm>
</aol-layer-tile>
<aol-layer-tile [zIndex]="2">
<aol-source-osm ></aol-source-osm>
</aol-layer-tile>
<aol-layer-vector  [opacity]="1"  [zIndex]="3">
<aol-source-vector>
<ng-container *ngFor="let item of api.datapoints">
<ng-container *ngIf="useCoord(item.latitude , item.longitude)">
<aol-feature [id]="item.uuid">
<aol-geometry-point>
<aol-coordinate [x]="item.longitude" [y]="item.latitude" [srid]="'EPSG:4326'"></aol-coordinate>
</aol-geometry-point>
<aol-style>
<aol-style-icon [src]="'./assets/img/'+item.icon" [anchor]="[0.5, 0.5]"
[anchorXUnits]="'fraction'"
[anchorYUnits]="'fraction'" [scale]="1" [anchorOrigin]="'top-left'">
</aol-style-icon>
</aol-style>
</aol-feature>
</ng-container>
</ng-container>
</aol-source-vector>
</aol-layer-vector>
</aol-map>

最新更新