On openlayers 3, how do you pause a change event when updating features?

浪尽此生 提交于 2020-01-25 04:40:45

问题


Basically, i have to update multiple features, specifically setGeometry, but everytime an update is applied on single feature, the change event is triggered, causing the layer to be redrawn. So, if there are 500 features updated, the layer will ve redrawn 500 times. I would like to payse the redraw event, untill all features are updated.

Update: One of the workaround that i can think of is:

  1. getFeatures()
  2. clear(true)
  3. (Updates the features)
  4. addFeatures(features)

But i'm not sure if there's a cleaner way than this


回答1:


Short answer:

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

Long answer:

After looking at the setGeometry source code (feature.js), basically it will use the set method on geometryName_. So by explicitly setting the same property and set opt_silent to true, it will not fire the change event (object.js).

Once you have completed the changes, just fire the change event on the layer.




回答2:


Don't skip the change events

The basic premise of the question - that each feature change results in a redraw of the layer - is incorrect.

When a feature changes, the map will request a redraw on the next animation frame. But if multiple features are changed within the same thread of execution, the browser won't redraw anything until the script finishes. You could loop through and change millions of features with only a single redraw.

You can verify when a render is done by listening to the postrender event:

map.on('postrender', function(event){
  console.log('did render', new Date())
})

You could set the geometry without triggering any events, as suggested in your answer. But doing so could cause issues such as a corrupt spatial index in the source. Omitting the change events should only be done if you know for sure that no one is interested in that change.

What delays are there then?

With that said, there's still a performance hit to updating a lot of features. I wrote this demo, which replaces all features' geometries on each map click. On my laptop, it takes around 600 milliseconds to replace all 10 000 geometries. During that time, the map and the browser is unresponsive and no updates are shown until the next redraw. The duration of the redraw depends on the zoom level.

When settings the geometry on a feature, it will:

  • add the geometry to it's properties
  • remove any listeners to the previous geometry.
  • add change listeners to the new geometry.
  • trigger a change event to notify listeners that it has changed.

On of the listeners of the feature will be the source, which will:

  • update the spatial index, if used.
  • trigger a change event to notify listeners that it has changed.

The layer and eventually the map will we notified of these changes, and queue a redraw.

Possible optimizations

If you wish to be able to change many features in a more performant way, I'd suggest considering:

Disabling the spatial index

As noted in the docs, setting useSpatialIndex to false may increase performance in some situations. Without the spatial index, the source has less computations to do on each feature change. Other uses of the source might become less performant without the index, though.

Modifying the geometry instead of replacing it

Using setCoordinates on the geometry is faster than using setGeometry on the feature. The whole Geometry instance creation can be skipped, and no listeners has to be modified. This assumes that you can modify the geometry, such as if the feature is the sole 'owner' of the geometry.

Trying to split the feature modifications into smaller chunks

This is contrary to the intent of the question. If it takes a lot of time to modify the features, you probably want to trigger a render more often. That would make the map appear more responsive, as well as allowing the browser to catch up on handling events and other pending tasks.



来源:https://stackoverflow.com/questions/36974264/on-openlayers-3-how-do-you-pause-a-change-event-when-updating-features

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!