我尝试根据来自OSM的代码示例实现用于 OSM 嵌入的 Angular 组件。事实证明这很难。:(
这是我到目前为止的代码:
import { Component, Input, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'app-osm',
templateUrl: './osm.component.html',
styleUrls: ['./osm.component.scss']
})
export class OsmComponent implements OnInit {
@Input() latitude: number;
@Input() longitude: number;
@Input() zoom: number;
public iframeSrc;
public extMapSrc;
constructor(
private sanitizer: DomSanitizer
) { }
ngOnInit(): void {
const bbox = this.boundaryBox(this.latitude, this.longitude, 1100, 400, 16);
this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(
`https://www.openstreetmap.org/export/embed.html` +
`?bbox=${bbox.join(',')}` +
`&layer=mapnik` +
`&marker=${this.latitude},${this.longitude}`
);
this.extMapSrc = this.sanitizer.bypassSecurityTrustUrl(
`https://www.openstreetmap.org/` +
`?mlat=${this.latitude}&mlon=${this.longitude}` +
`#map=17/${this.latitude}/${this.longitude}`
);
}
lonToTile(lon: number, zoom: number): number {
return (Math.floor((lon + 180) / 360 * Math.pow(2, zoom)));
}
latToTile(lat: number, zoom: number): number {
return Math.floor(
(1 - Math.log(
Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)
) / Math.PI) / 2 * Math.pow(2, zoom)
);
}
tileToLon(x: number, zoom: number): number {
return (x / Math.pow(2, zoom) * 360 - 180);
}
tileToLat(y: number, zoom: number): number {
const n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom);
return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
}
boundaryBox(
lat: number,
lon: number,
width: number = 1110,
height: number = 400,
zoom: number = 17,
) {
const tileSize = 256;
const lonTile = this.lonToTile(lon, zoom);
const latTile = this.latToTile(lat, zoom);
const minLonTile = (lonTile * tileSize - width / 2) / tileSize;
const minLatTile = (latTile * tileSize - height / 2) / tileSize;
const maxLonTile = (lonTile * tileSize + width / 2) / tileSize;
const maxLatTile = (latTile * tileSize + height / 2) / tileSize;
const minLon = this.tileToLon(minLonTile, zoom);
const minLat = this.tileToLat(minLatTile, zoom);
const maxLon = this.tileToLon(maxLonTile, zoom);
const maxLat = this.tileToLat(maxLatTile, zoom);
return [minLon, minLat, maxLon, maxLat];
}
}
它(有点)有效,尽管由于某种原因地图定位并不完全正确。