我正在使用 Azure Maps,并试图围绕他们的 maps web sdk 创建一个可重用的库。我想为用户提供一种方法来传递他们自己的弹出窗口以及数组强类型对象,以向页面添加标记。我有地图和标记工作,但我坚持如何将数据传递到弹出窗口。目前我有:
az-map.component.html
<div class="map-wrapper">
<div id="az-map"></div>
</div>
<ng-template #defaultMarker>
<div>
<img alt="" src="https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi2.png" />
</div>
</ng-template>
<ng-template #defaultPopup>
<div>
<h2>~name~</h2>
</div>
</ng-template>
<div style="display:none">
<div id="marker" #marker>
<ng-container *ngTemplateOutlet="markerTemplate ? markerTemplate : defaultMarkerTemplate"></ng-container>
</div>
<div id="popup" #popup>
<ng-content select="[popupTemplate]"></ng-content>
</div>
</div>
az-map.component.ts
@Component({
selector: 'az-map',
templateUrl: './azure-map.component.html',
styleUrls: ['./azure-map.component.scss']
})
export class AzureMapComponent implements OnInit {
@Input() locations: Location[];
@Input() mapConfig: AzureMapConfig;
@Input() markerTemplate: TemplateRef<any>;
@ViewChild('defaultMarker') defaultMarkerTemplate: TemplateRef<any>;
@ViewChild("popup") popupElement: ElementRef;
@ViewChild("marker") marker: ElementRef;
/* These are the map components we can interact with */
public map: any;
public popup: atlas.Popup;
public symbolLayer: atlas.layer.SymbolLayer;
private dataSource: atlas.source.DataSource;
constructor(private configService: ConfigurationService) { }
ngOnInit() {
const centerPosition: any = this.mapConfig.center.length
? this.mapConfig.center
: ( this.locations && this.locations.length > 0 ? [this.locations[0].longitude, this.locations[0].latitude] : [-95, 38]);
this.map = new atlas.Map('az-map', {
center: centerPosition,
zoom: this.mapConfig.zoom,
authOptions: {
authType: atlas.AuthenticationType.subscriptionKey,
subscriptionKey: this.configService.get().azureMapKey
}
});
this.map.events.add('ready', () => {
this.dataSource = new atlas.source.DataSource();
this.map.sources.add(this.dataSource);
this.addMarkers();
this.symbolLayer = new atlas.layer.SymbolLayer(this.dataSource, null)
this.map.layers.add(this.symbolLayer);
if (this.mapConfig.showControls) {
this.map.controls.add(new atlas.control.ZoomControl(), {
position: "top-right"
});
}
if(this.mapConfig.showPopups){
this.popup = new atlas.Popup({
pixelOffset: [0, -18],
closeButton: false
});
const _this = this;
this.map.events.add('mouseover', this.symbolLayer, (e) => {
if (e.shapes && e.shapes.length > 0) {
var coordinate;
const popupHtml = _this.popupElement.nativeElement.innerHTML;
var props = e.shapes[0].getProperties();
coordinate = e.shapes[0].getCoordinates();
_this.popup.setOptions({
//Update the content of the popup.
content: popupHtml,
//Update the popup's position with the symbol's coordinate.
position: coordinate
});
//Open the popup.
_this.popup.open(_this.map);
}
});
this.map.events.add('mouseleave', this.symbolLayer, (e) => {
this.popup.close()
});
}
});
}
private addMarkers(): void {
const html = this.marker.nativeElement.innerHTML;
this.locations.forEach(l => {
const point = new atlas.Shape( new atlas.data.Point([l.longitude, l.latitude]));
this.dataSource.add(point);
});
}
}
以及此处使用的示例:
<h1>Account Coverage</h1>
<div class="map-wrapper col-12">
<az-map [mapConfig]="mapConfig" [locations]="locations" class="col-12 h-50">
<coverage-popup popupTemplate></coverage-popup>
</az-map>
</div>
这有效并显示了弹出窗口,但我需要找到一种方法在 az-maps.component.ts 的 mouseover 事件中将数据传递给 CoveragePopupComponent
我们尝试使用的一种方法,当您只有一个需要处理的弹出类型时效果很好,就是像这样使用 ComponentFactoryResolver:
const factory = this.componentFactoryResolver.resolveComponentFactory(PopupComponent);
const component = factory.create(this.injector);
component.instance.machine = shape.getProperties();
component.changeDetectorRef.detectChanges();
const popupContent = component.location.nativeElement;
this.map.setCamera({
center: shape.getCoordinates(),
type: 'ease',
});
this.popup.setOptions({
position: shape.getCoordinates(),
content: popupContent,
pixelOffset: [0, -20]
});
this.popup.open(this.map);
但是你总是必须使用 PopupComponent 类型并且不能使用我们在地图模板中的 ng-content 东西。