Javascript 在openlayers 3上,更新功能时如何暂停更改事件?

Javascript 在openlayers 3上,更新功能时如何暂停更改事件?,javascript,openlayers-3,Javascript,Openlayers 3,基本上,我必须更新多个要素,特别是setGeometry,但每次对单个要素应用更新时,都会触发更改事件,导致重新绘制图层。因此,如果更新了500个特征,该层将重新绘制500次。 我想支付重画事件,直到所有功能更新 更新: 我能想到的解决办法之一是: getFeatures() 清晰(真实) (更新功能) 添加功能(功能) 但我不确定是否有比这更干净的方法简短的回答: var feature = layer.getFeatureById("myId"); var geometry = new ol

基本上,我必须更新多个要素,特别是setGeometry,但每次对单个要素应用更新时,都会触发更改事件,导致重新绘制图层。因此,如果更新了500个特征,该层将重新绘制500次。 我想支付重画事件,直到所有功能更新

更新: 我能想到的解决办法之一是:

  • getFeatures()
  • 清晰(真实)
  • (更新功能)
  • 添加功能(功能)

  • 但我不确定是否有比这更干净的方法

    简短的回答:

    var feature = layer.getFeatureById("myId");
    var geometry = new ol.geom.Point(ol.proj.fromLonLat([lon, lat]));
    feature.set(feature.getGeometryName(), geometry, true);
    ........
    source.changed()
    
    长答案:

    var feature = layer.getFeatureById("myId");
    var geometry = new ol.geom.Point(ol.proj.fromLonLat([lon, lat]));
    feature.set(feature.getGeometryName(), geometry, true);
    ........
    source.changed()
    
    在查看了setGeometry源代码()之后,基本上它将在geometryName上使用set方法。因此,通过显式设置相同的属性并将opt_silent设置为true,它将不会触发更改事件()


    完成更改后,只需在图层上触发更改事件。

    简短回答:

    var feature = layer.getFeatureById("myId");
    var geometry = new ol.geom.Point(ol.proj.fromLonLat([lon, lat]));
    feature.set(feature.getGeometryName(), geometry, true);
    ........
    source.changed()
    
    长答案:

    var feature = layer.getFeatureById("myId");
    var geometry = new ol.geom.Point(ol.proj.fromLonLat([lon, lat]));
    feature.set(feature.getGeometryName(), geometry, true);
    ........
    source.changed()
    
    在查看了setGeometry源代码()之后,基本上它将在geometryName上使用set方法。因此,通过显式设置相同的属性并将opt_silent设置为true,它将不会触发更改事件()


    完成更改后,只需在图层上触发更改事件。

    不要跳过更改事件

    这个问题的基本前提——每个特征的改变都会导致图层的重新绘制——是不正确的

    当特征更改时,贴图将在下一个动画帧上请求重画。但是,如果在同一执行线程中更改了多个功能,则在脚本完成之前,浏览器不会重新绘制任何内容。只需一次重画,您就可以循环并更改数百万个功能

    您可以通过侦听
    postdrender
    事件来验证渲染何时完成:

    map.on('postrender', function(event){
      console.log('did render', new Date())
    })
    
    可以在不触发任何事件的情况下设置几何图形,如中所示。但这样做可能会导致诸如源中的空间索引损坏之类的问题。只有当您确信没有人对更改感兴趣时,才应该省略更改事件

    那么会有什么延迟?

    尽管如此,更新许多功能仍然会对性能造成影响。我写道,它会在每次地图点击时替换所有特征的几何图形。在我的笔记本电脑上,更换所有10000个几何图形大约需要600毫秒。在此期间,地图和浏览器没有响应,在下次重画之前不会显示任何更新。重画的持续时间取决于缩放级别

    在要素上设置几何图形时,它将:

    • 将几何图形添加到其属性中
    • 删除上一个几何体的所有侦听器
    • 将更改侦听器添加到新几何图形
    • 触发更改事件以通知侦听器它已更改
    在功能的侦听器上,将是源,它将:

    • 更新空间索引(如果使用)
    • 触发更改事件以通知侦听器它已更改
    我们会将这些更改通知图层和地图,并将重画排队

    可能的优化

    如果您希望能够以更高效的方式更改许多功能,我建议您考虑:

    禁用空间索引

    如中所述,在某些情况下,将
    useSpatialIndex
    设置为false可能会提高性能。在没有空间索引的情况下,源对每个特征变化的计算量较少。不过,如果没有索引,源代码的其他用途可能会变得性能较差

    修改几何图形而不是替换它

    在几何图形上使用
    setCoordinates
    比在特征上使用
    setGeometry
    更快。可以跳过整个几何体实例创建,并且不必修改侦听器。这假设您可以修改几何图形,例如如果特征是几何图形的唯一“所有者”

    尝试将功能修改拆分为更小的块


    这与问题的意图背道而驰。如果修改功能需要很多时间,则可能需要更频繁地触发渲染。这将使地图更具响应性,并允许浏览器及时处理事件和其他未决任务。

    不要跳过更改事件。

    这个问题的基本前提——每个特征的改变都会导致图层的重新绘制——是不正确的

    当特征更改时,贴图将在下一个动画帧上请求重画。但是,如果在同一执行线程中更改了多个功能,则在脚本完成之前,浏览器不会重新绘制任何内容。只需一次重画,您就可以循环并更改数百万个功能

    您可以通过侦听
    postdrender
    事件来验证渲染何时完成:

    map.on('postrender', function(event){
      console.log('did render', new Date())
    })
    
    可以在不触发任何事件的情况下设置几何图形,如中所示。但这样做可能会导致诸如源中的空间索引损坏之类的问题。只有当您确信没有人对更改感兴趣时,才应该省略更改事件

    那么会有什么延迟?

    尽管如此,更新许多功能仍然会对性能造成影响。我写道,它会在每次地图点击时替换所有特征的几何图形。在我的笔记本电脑上,更换所有10000个几何图形大约需要600毫秒。在此期间,地图和浏览器没有响应,在下次重画之前不会显示任何更新。重画的持续时间取决于缩放级别

    在要素上设置几何图形时,它将:

    • 添加几何体