Deckgl与Google Maps图层重叠时点击事件冲突问题求助
问题:Google Maps Polygon与Deck.gl ScatterplotLayer重叠时点击事件冲突
在Google Maps中同时使用Polygon和Deck.gl的ScatterplotLayer,两者均配置了点击事件,图层未重叠时事件可正常触发,但当ScatterplotLayer被Polygon覆盖后,其点击事件失效。需求是同时触发两个图层的点击事件,且不能通过clickable: false禁用Polygon的点击事件。即使为deck.GoogleMapsOverlay设置style.zIndex: 10000,Polygon仍会捕获点击事件,无法传递给Deck.gl图层。
解决方案1:利用地图点击事件手动触发Deck.gl拾取
Google Maps的地图点击事件可获取点击坐标,通过Deck.gl的pickObject方法手动检测点击位置是否命中ScatterplotLayer元素,从而触发对应逻辑。
修改后代码示例
// Initialize the Google Map const map = new google.maps.Map(document.getElementById('map'), { center: { lat: 51.47, lng: 0.45 }, zoom: 11, }); // Define the coordinates for the polygon const polygonCoords = [ { lat: 51.47, lng: 0.45 }, { lat: 51.48, lng: 0.46 }, { lat: 51.49, lng: 0.45 }, { lat: 51.48, lng: 0.44 }, ]; // Create a Google Maps polygon const polygon = new google.maps.Polygon({ paths: polygonCoords, strokeColor: '#FF0000', strokeOpacity: 0.8, strokeWeight: 2, fillColor: '#FF0000', fillOpacity: 0.35, }); polygon.setMap(map); // Create a deck.gl ScatterplotLayer const scatterplotLayer = new deck.ScatterplotLayer({ id: 'scatterplot-layer', data: [{ position: [0.45, 51.47] }], getPosition: d => d.position, getFillColor: [255, 0, 0, 100], getRadius: 1000, pickable: true, }); // Create GoogleMapsOverlay const overlay = new deck.GoogleMapsOverlay({ layers: [scatterplotLayer], interleaved: false, }); overlay.setMap(map); // Polygon点击事件:触发自身逻辑+检测Deck.gl拾取 google.maps.event.addListener(polygon, 'click', function(event) { alert('Polygon clicked at ' + event.latLng); const viewport = overlay.getViewport(); const screenPoint = viewport.project([event.latLng.lng(), event.latLng.lat()]); const pickedObject = overlay.pickObject({x: screenPoint[0], y: screenPoint[1]}); if (pickedObject) { alert('Deck.gl scatterplot clicked at ' + pickedObject.coordinate); } }); // 地图点击兜底:检测Deck.gl拾取 map.addListener('click', function(event) { console.log('Map clicked at: ', event.latLng); const viewport = overlay.getViewport(); const screenPoint = viewport.project([event.latLng.lng(), event.latLng.lat()]); const pickedObject = overlay.pickObject({x: screenPoint[0], y: screenPoint[1]}); if (pickedObject) { alert('Deck.gl scatterplot clicked at ' + pickedObject.coordinate); } });
解决方案2:穿透Polygon点击+手动检测Polygon范围
设置Polygon的clickable: false让点击穿透到Deck.gl,再在Deck.gl的点击事件中检测点击是否在Polygon范围内,触发Polygon逻辑。
修改后代码示例
// Initialize the Google Map const map = new google.maps.Map(document.getElementById('map'), { center: { lat: 51.47, lng: 0.45 }, zoom: 11, }); // Define the coordinates for the polygon const polygonCoords = [ { lat: 51.47, lng: 0.45 }, { lat: 51.48, lng: 0.46 }, { lat: 51.49, lng: 0.45 }, { lat: 51.48, lng: 0.44 }, ]; // 创建Polygon并设置clickable: false const polygon = new google.maps.Polygon({ paths: polygonCoords, strokeColor: '#FF0000', strokeOpacity: 0.8, strokeWeight: 2, fillColor: '#FF0000', fillOpacity: 0.35, clickable: false }); polygon.setMap(map); // Create a deck.gl ScatterplotLayer const scatterplotLayer = new deck.ScatterplotLayer({ id: 'scatterplot-layer', data: [{ position: [0.45, 51.47] }], getPosition: d => d.position, getFillColor: [255, 0, 0, 100], getRadius: 1000, pickable: true, onClick: (info) => { alert('Deck.gl scatterplot clicked at ' + info.coordinate); // 检测点击是否在Polygon范围内 const latLng = new google.maps.LatLng(info.coordinate[1], info.coordinate[0]); if (google.maps.geometry.poly.containsLocation(latLng, polygon)) { alert('Polygon clicked at ' + latLng); } } }); // Create GoogleMapsOverlay const overlay = new deck.GoogleMapsOverlay({ layers: [scatterplotLayer], interleaved: false, }); overlay.setMap(map); // 地图点击兜底:检测Polygon范围 map.addListener('click', function(event) { console.log('Map clicked at: ', event.latLng); if (google.maps.geometry.poly.containsLocation(event.latLng, polygon)) { alert('Polygon clicked at ' + event.latLng); } });
注意:需在Google Maps API加载时添加
&libraries=geometry参数,引入几何库。
解决方案3:用Deck.gl PolygonLayer替代Google Maps Polygon
将Google Maps的Polygon替换为Deck.gl的PolygonLayer,所有图层统一在Deck.gl渲染管线中,通过Deck.gl事件系统同时处理点击,避免DOM层级冲突。
修改后代码示例
// Initialize the Google Map const map = new google.maps.Map(document.getElementById('map'), { center: { lat: 51.47, lng: 0.45 }, zoom: 11, }); // 转换Polygon坐标为Deck.gl的[lon, lat]格式 const polygonCoords = [ [0.45, 51.47], [0.46, 51.48], [0.45, 51.49], [0.44, 51.48], ]; // Create deck.gl PolygonLayer const polygonLayer = new deck.PolygonLayer({ id: 'polygon-layer', data: [{ polygon: polygonCoords }], getPolygon: d => d.polygon, getFillColor: [255, 0, 0, 89], // 对应fillOpacity:0.35 getLineColor: [255, 0, 0], getLineWidth: 2, pickable: true, onClick: (info) => { alert('Polygon clicked at ' + info.coordinate); } }); // Create deck.gl ScatterplotLayer const scatterplotLayer = new deck.ScatterplotLayer({ id: 'scatterplot-layer', data: [{ position: [0.45, 51.47] }], getPosition: d => d.position, getFillColor: [255, 0, 0, 100], getRadius: 1000, pickable: true, onClick: (info) => { alert('Deck.gl scatterplot clicked at ' + info.coordinate); } }); // Create GoogleMapsOverlay const overlay = new deck.GoogleMapsOverlay({ layers: [polygonLayer, scatterplotLayer], // 图层顺序:后添加的在上层 interleaved: false, }); overlay.setMap(map); // 地图点击兜底 map.addListener('click', function(event) { console.log('Map clicked at: ', event.latLng); });
内容的提问来源于stack exchange,提问作者SERG
相关产品推荐
相关产品推荐

