【问题标题】:Cannot set a style for clicked features in vector layer无法为矢量图层中单击的要素设置样式
【发布时间】:2015-10-24 20:02:36
【问题描述】:

所以在我的 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];
}

当点击一个功能时,我希望该功能更改其样式,其余部分保持上面的默认样式。

这是我的尝试

 //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);

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

那么,我该如何解决这个问题,还有,有没有更简单的方法来做到这一点?我认为这种功能需要很多代码

谢谢

编辑

我换了

    for (i in e.selected){
        e.selected[i].setStyle(styleFunction);  
    }

与

    var allfe = sourceVector.getFeatures(); 

    for (i in allfe){
        allfe[i].setStyle(styleFunction);   
    }   

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

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

我不能只设置一个样式,我需要它是一个函数,这样我以后可以检查几何类型。

所以我的两个问题,

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

如果我有 500 个特征,每次点击都重绘所有特征,会减慢渲染速度。有没有其他解决方案?

谢谢

【问题讨论】:

  • 嘿,@slevin,结果如何?

标签: openlayers-3


【解决方案1】:

图层和特征样式功能不同

使用 OpenLayers 3 风格的函数时,您必须注意 ol.FeatureStyleFunction 和 ol.style.StyleFunction 之间的区别。它们非常相似,因为它们都应该基于特性和分辨率返回一个 ol.Styles 数组。然而,他们并没有以同样的方式获得这些信息。

当为特性提供样式函数时,使用它的setStyle 方法,函数应该是ol.FeatureStyleFunction。调用 ol.FeatureStyleFunction 时使用 this 引用该功能,并使用 resolution 作为唯一参数。

为图层提供样式功能时,它应该是ol.style.StyleFunction。它们使用两个参数调用,feature 和 resolution。

这是您的错误的原因。您正在使用 ol.style.StyleFunction 作为特征样式。稍后,当调用您的样式函数时,第一个参数是分辨率,而不是您期望的功能。

解决方案一:setStyle(null)

这个解决方案已经在@jonatas-walker 的answer 中提出。它的工作原理是为您选择的功能设置样式并从未选择的功能中删除样式(而不是将您的样式功能设置为未选择的功能)。

OpenLayers 将使用该要素的样式(如果有),否则使用图层的样式。所以将未选中的要素的样式重新设置为null,会使它们再次使用图层的样式功能。

解决方案 2:使用您选择的交互的 style 选项 ol.interaction.Select 接受一个样式选项(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);

【讨论】:

  • 很好解释的答案。分红吧?
  • @JonatasWalker 谢谢。是否可以拆分赏金?
  • 开个玩笑。我不这么认为。
  • @AlvinLindstam 所以,要创建一个 ol.FeatureStyleFunction 我必须做 function styleFunction3(resolution) { var color = this.p_color; //set fill, stroke etc.... 。但是var color = this.color; 和var color = this.get('color'); 都会抛出错误。那么我如何从要设置样式的功能中获取数据?谢谢
  • @slevin:是的,ol.FeatureStyleFunction this 将引用该功能。如果您遇到这些错误,您可能将 ol.FeatureStyleFunction 设置在图层/交互而不是功能上。 Se Jonatas 对使用 this 获取 ol.FeatureStyleFunction 中的功能的工作示例的回答。
【解决方案2】:

更新 - fiddle styling with ol.interaction.Select

怎么样 - http://jsfiddle.net/jonataswalker/zz6d4z7d/

var select = new ol.interaction.Select();
map.addInteraction(select);

var styleClick = function() {
    // `this` is ol.Feature
    return [
        new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({ color: [245, 121, 0, 0.8] }),
                stroke: new ol.style.Stroke({ color: [0,0,0,1] }),
                radius: 7
            }),
            text: new ol.style.Text({
                font: '24px Verdana',
                text: this.get('name'),
                offsetY: 20,
                fill: new ol.style.Fill({
                    color: [255, 255, 255, 0.8]
                })
            })
        })
    ];
};

select.on('select', function(evt){
    var selected = evt.selected;
    var deselected = evt.deselected;

    selected.forEach(function(feature){
        feature.setStyle(styleClick);
    });

    deselected.forEach(function(feature){
        feature.setStyle(null);
    });
});

【讨论】:

  • 比我的更快、更简单的 hack。好的!谢谢!这里真正的问题是 OL 实际上是如何处理这个问题的?正如 Alvin 指出的那样,您可以在设置交互时为所选功能设置样式。该样式仅访问和更改已选择/未选择的功能(=您的解决方案,更快)还是所有功能(=我的解决方案,更慢)?如果第二个是正确的,那么您的解决方案会更快,并且值得在原生 OL 解决方案上使用它。我认为你应该在 gitHub 上发表评论,让社区知道。
  • 我不认为有性能差异,但可以肯定ol.interaction.Select 中的代码样式更少。这取决于你。
  • 我想最好还是使用@AlvinLindstam 的回答。
  • @JonatasWalker 感谢您的时间和精力。不错,干净的答案和代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多