无法为矢量图层中的单击要素设置样式

sle*_*vin 4 openlayers-3

所以在我的Openlayers 3中,我设置了一个默认样式,它在第一次加载图层时呈现特征

function styleFunction(feature, resolution) {
    var color = feature.get('color');
    var name = feature.get('name');

    var fill = new ol.style.Fill({
        color: color
    });

    var stroke = new ol.style.Stroke({
        color: "black",
        lineCap: "butt",
        lineJoin: "bevel",
        width:1         
    });

    var text= new ol.style.Text({
        font: '20px Verdana',
        text: name,
        fill: new ol.style.Fill({
            color: [64, 64, 64, 0.5]
        })
    })

    var cStyle = new ol.style.Style({
        fill: fill,
        stroke: stroke,
        text: text
    });

    return [cStyle];
}
Run Code Online (Sandbox Code Playgroud)

单击某个功能时,我希望该功能更改其样式,其余部分保持上面的默认样式.

这是我尝试这样做的

 //add simple click interaction to the map
 var select = new ol.interaction.Select();
 map.addInteraction(select);

//for every clicked feature
 select.on('select', function(e) {
       var name = e.selected[0].get('name');

       //set the clicked style
        var fillClick= new ol.style.Fill({
            color: "black"
         });

        var strokeClick = new ol.style.Stroke({
            color: "white",
            lineCap: "butt",
            lineJoin: "bevel",
            width:3         
        });

        var textClick= new ol.style.Text({
                font: '10px Verdana',
                text: name,
                fill: new ol.style.Fill({
                    color: [64, 64, 64, 1]
                })
            })

        var styleClick = new ol.style.Style({
            stroke: strokeClick,
            fill : fillClick,
            text : textClick
        });



    //set all to default
    for (i in e.selected){
        e.selected[i].setStyle(styleFunction);  
    }

    //reset the first selected to the clicked style
    e.selected[0].setStyle(styleClick);
Run Code Online (Sandbox Code Playgroud)

我在控制台上没有任何错误,但这不会起作用.单击另一个时,单击的功能将不会返回到默认样式.所有点击的功能都保留了styleClick.

那么,我该如何解决这个问题,还有一种更简单的方法吗?我认为它有很多代码用于这种功能

谢谢

编辑

我换了

    for (i in e.selected){
        e.selected[i].setStyle(styleFunction);  
    }
Run Code Online (Sandbox Code Playgroud)

    var allfe = sourceVector.getFeatures(); 

    for (i in allfe){
        allfe[i].setStyle(styleFunction);   
    }   
Run Code Online (Sandbox Code Playgroud)

所以现在所有功能都将获得styleFunction函数中定义的样式.

这不起作用.我Uncaught TypeError: feature.get is not a function指的是函数的第一行,var color = feature.get('color');这一行.

我不能只设置一个样式,我需要它作为一个函数,所以我可以在将来检查几何类型.

所以我的两个问题,

我不知道如何调试和修复此错误

如果我有500个功能,每次点击重绘所有功能都会降低渲染速度.还有另一个解决方案吗?

谢谢

Alv*_*tam 13

图层和要素样式功能是不同的

使用OpenLayers 3样式函数时,您必须注意ol.FeatureStyleFunctiona和a 之间的区别ol.style.StyleFunction.它们非常相似,因为它们都应该ol.Style根据特征和分辨率返回一个s 数组.但是,它们没有以相同的方式提供该信息.

当为特征提供样式函数时,使用它的setStyle方法,该函数应该是一个ol.FeatureStyleFunction.ol.FeatureStyleFunction通过this引用该功能调用An ,并将其resolution作为唯一参数.

为图层提供样式函数时,它应该是一个ol.style.StyleFunction.它们被调用两个参数,即featureresolution.

这是导致错误的原因.您使用的ol.style.StyleFunction是一种功能样式.之后,当调用样式函数时,第一个参数是分辨率而不是您期望的特征.

解决方案1:setStyle(null)

@ jonatas-walker的答案已经提出了这个解决方案.它的工作原理是在所选要素上设置样式,并从未选择的要素中删除样式(而不是将样式函数设置为未选择的要素).

OpenLayers将使用该功能的样式(如果有),否则使用图层的样式.因此,将未选择的要素样式重新设置为null将使它们再次使用图层的样式函数.

解决方案2:使用style选择交互 ol.interaction.Select选项接受样式选项(an ol.style.StyleFunction),该选项用于设置所选要素的样式.

优点:为图层(普通视图)设置一个样式函数,为选择交互设置样式函数,使代码比混合特征和图层样式更具可读性.此外,您不必跟踪事件或修改功能.

可以这样做:

var selectedStyleFunction = function(feature, resolution) {
    return [new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: "white",
            lineCap: "butt",
            lineJoin: "bevel",
            width:3         
        }),
        fill : new ol.style.Fill({
            color: "black"
        }),
        text : new ol.style.Text({
            font: '10px Verdana',
            text: feature.get('name'),
            fill: new ol.style.Fill({
                color: [64, 64, 64, 1]
            })
        })
    })];
};
var select = new ol.interaction.Select({
    style: selectedStyleFunction
});
map.addInteraction(select);
Run Code Online (Sandbox Code Playgroud)