Feature选取之条件过滤

涉及到选取,自然会有各种条件用于过滤,比如是鼠标左键单击,还是双击,是可以选取地图上的任意feature,还是某一类的feature。 对于这些需求,ol.interaction.Select都能满足,在API的文档里面就有相关的参数设置,下面就是一些简单的使用示例。

改变默认的单击选取方式

默认情况下,是支持鼠标左键单击选取feature的,在地图上其他地方点击一下,就取消选取了,但这并不是定死的选取方式,你完全可以自定义。 比如鼠标移动到feature上,就选取了,试试:

代码同之前的例子只有一个地方不同:

<div id="map" style="width: 100%"></div>
<script type="text/javascript">
    var layer = new ol.layer.Vector({
        source: new ol.source.Vector(),
        style: new ol.style.Style({
            image: new ol.style.Circle({
                radius: 10,
                fill: new ol.style.Fill({
                    color: 'red'
                })
            })
        })
    });
    var map = new ol.Map({
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          }), 
          layer
        ],
        target: 'map',
        view: new ol.View({
          center: ol.proj.transform(
              [104, 30], 'EPSG:4326', 'EPSG:3857'),
          zoom: 10
        })
    });

    // 在地图上添加一个圆
    var circle = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.transform(
              [104, 30], 'EPSG:4326', 'EPSG:3857'))
    })
    layer.getSource().addFeature(circle);

    // 添加一个用于选择Feature的交互方式
    map.addInteraction(new ol.interaction.Select({
        condition: ol.events.condition.pointerMove,     // 唯一的不同之处,设置鼠标移到feature上就选取
        style: new ol.style.Style({
            image: new ol.style.Circle({
                radius: 10,
                fill: new ol.style.Fill({
                    color: 'blue'
                })
            })
        })
    }));
</script>

ol.events.condition里面有很多内置的条件过滤函数,可以在官网API查询,如果内置方式没有,也可以自己写一个类似的函数,比如:

ol.events.condition.singleClick = function(mapBrowserEvent) {
  return mapBrowserEvent.type == ol.MapBrowserEvent.EventType.SINGLECLICK;
};

就只是一个类型判断而已,是否非常的简单,任何人都可以自定义一个这种条件过滤函数。

直接对feature过滤

除了可以自定义选取的交互方式之外,我们还可以对feature进行过滤,如果当前选取的并不是我们需要的feature,我们可以决定不选取。 比如我们只希望用户能选取圆形,而不能选取五星,选取方式为默认的单击:

代码其实也是非常简单,前面大部分代码都是一样的,关键在最后:

<div id="map2" style="width: 100%"></div>
<script type="text/javascript">
    // 创建一个用于存放circle的layer
    var circleLayer = new ol.layer.Vector({
        source: new ol.source.Vector(),
        style: new ol.style.Style({
            image: new ol.style.Circle({
                radius: 10,
                fill: new ol.style.Fill({
                    color: 'red'
                })
            })
        })
    });

    // 创建一个用于存放star的layer
    var starLayer = new ol.layer.Vector({
        source: new ol.source.Vector(),
        style: new ol.style.Style({
            image: new ol.style.RegularShape({
                points: 5,
                radius1: 20,
                radius2: 10,
                fill: new ol.style.Fill({
                    color: 'red'
                })
            })
        })
    });

    var map2 = new ol.Map({
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          }), 
          circleLayer, starLayer
        ],
        target: 'map2',
        view: new ol.View({
          center: ol.proj.transform(
              [104, 30], 'EPSG:4326', 'EPSG:3857'),
          zoom: 10
        })
    });

    // 在地图上添加一个圆
    var circle1 = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.transform(
              [104, 30], 'EPSG:4326', 'EPSG:3857'))
    })
    circleLayer.getSource().addFeature(circle1);

    // 在地图上添加一个五星
    var star = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.transform(
              [104.06, 30.05], 'EPSG:4326', 'EPSG:3857'))
    })
    starLayer.getSource().addFeature(star);

    // 添加一个用于选择Feature的交互方式
    map2.addInteraction(new ol.interaction.Select({
        style: new ol.style.Style({
            image: new ol.style.Circle({
                radius: 10,
                fill: new ol.style.Fill({
                    color: 'blue'
                })
            })
        }),
        // 关键: 设置过了条件,可以用feature来写过滤,也可以用layer来写过滤
        filter: function(feature, layer){
            return layer === circleLayer;
        }
    }));
</script>

选取多个feature

前面的例子都只是一个feature的情况,在实际应用中,肯定是不止一个的,如果要能同时选择多个,只需要设置一下构造函数的参数multi: true,默认情况下,只能选取一个feature。 仿照上面的代码,可自行尝试。