Leaflet - 如何从地图外部选择要素

时间:2016-01-18 15:36:52

标签: angularjs leaflet angular-leaflet-directive

给定两个div:地图视图和每个行对应一个要素名称的侧面板,如何确保侧面板上的点击事件选择地图中的相应要素?

这对弹出窗口是可行的,但我想选择该功能,而不是创建标记或弹出窗口。使用Angular和angular-leaflet-directive,我有这个观点:

<div class="preview-wrapper container-fluid">
    <div class="row">
        <div class="col-md-8">
            <leaflet id="map-preview" geojson="geojson" center="nyc"></leaflet>
        </div>
        <div class="col-md-4">
            <div class="toolbox panel panel-default">
                <div class="panel-heading">
                    <div class="panel-title text-center">Toolbox</div>
                </div>
                <div class="panel-body">
                    <div class="row" ng-repeat="segment in trails" ng-click="toolboxTrailSelect(segment)">{{ segment.properties.name }}</div>
                </div>
            </div>
        </div>
    </div>
</div>

如您所见,ng-repeat只是输出控制器中定义的功能名称:

angular.module('dataUpload')
.controller('MapPreviewCtrl', function($scope, $log, $window, leafletData, fileReader) {
    "use strict";


    $scope.toolboxTrailSelect = function(obj) {
        $log.debug(obj);
        var latLng = new L.LatLng(obj.geometry.coordinates[0][0], obj.geometry.coordinates[0][1]);

        leafletData.getMap('map-preview').then(function(map) {
            map.fireEvent('click', {
                latlng : latLng,
                containerPoint : map.latLngToContainerPoint(latLng),
                layerPoint : map.latLngToLayerPoint(latLng)
            });
        });
    };

    leafletData.getMap('map-preview').then(function(map) {
        mapContainer = map;
        var kml = fileReader.getLocalFile();

        if (kml === null)
            $log.error("No file loaded");
        else {
            var data = getData();

            try {
                map.fitBounds(data.latlng);

                angular.extend($scope, {
                    geojson : {
                        data : data.geojson,
                        style : {
                            stroke : true,
                            weight : 5,
                            color : '#000000'
                        },
                        onEachFeature : function(feature, layer) {
                            layer.on('click', function(e) {
                                    $log.debug('Path click event: ' + e);
                                }
                            );
                        }
                    }
                });

            } catch (e) {
                $log.error(e.message);
                $window.alert(e.message);
            }
        }
    });
});

当控制器实例化时,它会将所有要素的几何和属性添加到范围中,然后在ng-repeat指令中进行迭代。

现在,在每个功能上定义了一个单击处理程序,并输出调试消息。 sidepanel中的每一行都有一个由toolboxTrailSelect处理的点击事件。

这意味着侧板中的单击事件将获得第一个lat / lng坐标对,并根据该坐标对触发单击事件。这个事件将由地图功能的点击事件处理。

我从功能点击事件和侧面板点击事件中获取调试消息。但是当侧面板单击发生时,我没有得到功能点击处理程序调试消息。

1 个答案:

答案 0 :(得分:0)

看起来我在正确的轨道上,但错过了几个关键部分。在这里记录答案以防其他人遇到相同的情况。

首先,在项目中加入object-hash。由于GeoJSON并不总是包含ID,因此这允许基于您正在映射的功能的哈希值。

由于我需要将地图边界拟合到路径,因此我创建了一个由map.fitBounds()使用的LatLng点数组。因此,我能够在范围对象中使用功能哈希和值。

<div class="row" ng-repeat="segment in trails" 
     ng-click="toolboxTrailSelect(segment)">{{ segment.properties.name }}</div>

    $scope.toolboxTrailSelect = function(obj) {
        var hash = objectHash.sha1(obj);
        leafletData.getMap('map-preview').then(function(map) {
            map._layers[hash].fire('click');
        });
    };

传单映射对象包含内部值_layers,它是要素的ID映射。迭代

中的功能集时
           onEachFeature : function(feature, layer) {
               layer._leaflet_id = objectHash.sha1(feature);
               layer.on('click', function(e) {
                   $log.debug('Path click event: ' + e);
               });
           }

我可以将自己的ID添加到_leaflet_id值,然后将其存储在map._layers中。

现在,由于每个功能都是自己的图层,我需要做的就是从点击事件中哈希传入的对象,从地图中获取相应的图层并在其上触发点击事件。