Angular中Leaflet上显示CDK Overlay时位置样式加载失败求助
问题解决:Angular Leaflet中右键菜单(CDK Overlay)样式与位置异常
问题现象
- 在空白div中使用Angular CDK Overlay实现的右键菜单显示正常
- 在Leaflet地图上触发右键菜单时,无法加载Overlay的位置样式和自身样式
- 仅激活tooltip按钮时,Overlay的样式才会正常加载
相关代码
TypeScript 代码
const openPan = (val) => this.open(val); this.map.addEventListener('contextmenu' , openPan); open($event){ this.closePanel(); const positionStrategy = this.overlay.position() .flexibleConnectedTo($event.containerPoint) .withPositions([ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', } ]); this.overlayRef = this.overlay.create({ positionStrategy, scrollStrategy: this.overlay.scrollStrategies.close(), disposeOnNavigation: true }); this.overlayRef.attach(new TemplatePortal(this.userMenu, this.viewContainerRef)); this.sub = fromEvent<MouseEvent>(document, 'click') .pipe( filter(event => { const clickTarget = event.target as HTMLElement; return !!this.overlayRef && !this.overlayRef.overlayElement.contains(clickTarget); }), take(1) ).subscribe(() => this.closePanel()); }
HTML 代码
<div class="map" leaflet [leafletOptions]="options" (leafletDrawStart)="onDrawStart($event)" (contextmenu)="$event.preventDefault();" (leafletMapZoom)="eventZoom($event)" (leafletMapReady)="onMapReady($event)" > </div> <ng-template #userMenu cdkConnectedOverlay> <section class="user-menu"> <div>Option 1 </div> </section> </ng-template>
解决方案
1. 修正位置策略的目标坐标
Leaflet的contextmenu事件返回的containerPoint是相对于地图容器的像素坐标,但CDK Overlay的flexibleConnectedTo需要全局坐标,需转换坐标格式:
open($event){ this.closePanel(); // 获取地图容器DOM元素并转换坐标 const mapContainer = this.map.getContainer(); const containerRect = mapContainer.getBoundingClientRect(); const targetPosition = { x: containerRect.left + $event.containerPoint.x, y: containerRect.top + $event.containerPoint.y }; const positionStrategy = this.overlay.position() .flexibleConnectedTo(targetPosition) .withPositions([ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', } ]); // 后续代码保持不变 }
2. 提升Overlay层级
Leaflet地图默认z-index较高,会覆盖Overlay,需手动设置层级:
this.overlayRef = this.overlay.create({ positionStrategy, scrollStrategy: this.overlay.scrollStrategies.close(), disposeOnNavigation: true, panelClass: 'map-overlay-panel' // 添加自定义类 });
在全局样式文件中添加:
.map-overlay-panel { z-index: 10000 !important; /* 确保高于Leaflet地图层级(通常为400左右) */ }
3. 移除模板冲突指令
手动创建OverlayRef后,模板中的cdkConnectedOverlay会导致样式冲突,需移除:
<ng-template #userMenu> <section class="user-menu"> <div>Option 1 </div> </section> </ng-template>
4. 修正点击关闭事件监听
Leaflet会拦截部分事件冒泡,将监听对象从document改为地图容器:
const mapContainer = this.map.getContainer(); this.sub = fromEvent<MouseEvent>(mapContainer, 'click') .pipe( filter(event => { const clickTarget = event.target as HTMLElement; return !!this.overlayRef && !this.overlayRef.overlayElement.contains(clickTarget); }), take(1) ).subscribe(() => this.closePanel());
内容的提问来源于stack exchange,提问作者reymer retamozo lopez
相关产品推荐
相关产品推荐

