2016-05-02 8 views
0

基本的には、複数のフィーチャ、特にsetGeometryを更新する必要がありますが、単一のフィーチャで更新が適用されるたびに、変更イベントがトリガされ、レイヤが再描画されます。したがって、500の機能が更新されている場合、レイヤーは500回再描画されます。 すべての機能が更新されるまで、私は再描画イベントをお支払いしたいと思います。openlayers 3では、機能を更新する際にどのように変更イベントを一時停止しますか?

更新: 私は考えることができる回避策の一つは次のとおりです。

  1. getFeatures()
  2. クリア(真)
  3. は(更新機能)
  4. addFeatures(機能)

これよりもクリーナーな方法があるかわかりません。

+0

これはパフォーマンス上の問題であることを示す実際のデータはありますか? OpenLayersはこれを非常に効率的に処理する必要があり、早すぎる最適化は一般的には悪い考えです。 –

+0

レイヤーとソースのchangeイベントを聞きました。機能が更新されるたびに(それぞれの機能)、リビジョン番号が増えます。変更イベントが発生します。 – psyntium

+0

これは、ol3が各機能の変更に対して新しいレンダリングを行うことを意味するものではありません。プロファイラを使用して実際に問題があるかどうかを確認しようとしましたか、少なくともレンダリング関連のイベントを聞いてみましたか? –

答えて

1

短い答え:

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ソースコード(feature.js)を見た後、基本的にはgeometryName_セットメソッドを使用します。 。したがって、明示的に同じプロパティを設定してopt_silentをtrueに設定すると、変更イベント(object.js)は発生しません。

変更を完了したら、変更イベントをレイヤーで発生させるだけです。各レイヤーの再描画に変更した結果を備えていること - -

+0

これは、多くの問題と予期しない動作を引き起こす可能性があります。ソースは、空間インデックスを最新の状態に保つために、その機能をリッスンします。だからあなたは堕落した指数で終わることができます。 –

+0

私はol3が理由でopt_silentを持っていると思います。数百万の機能を更新すると想像してください。サイレントオプションがなければ、そのレイヤーは何百万回も再描画されます。 – psyntium

1

は変更イベント

質問の基本的な前提を省略しないでください間違っています。

機能が変更されると、マップは次のアニメーションフレームで再描画を要求します。しかし、複数の機能が同じ実行スレッド内で変更された場合、ブラウザはスクリプトが終了するまで何も再描画しません。 1回の再描画だけで何百万ものフィーチャーをループして変更することができます。

レンダリングがpostrenderイベントを聞くことによって行われているときは、確認することができます。

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

your answerで提案されているようにあなたは、任意のイベントをトリガすることなく、ジオメトリを設定することができます。しかし、そのようにすると、ソース内の壊れた空間インデックスなどの問題が発生する可能性があります。誰かがその変更に関心がないことを確実に知っている場合にのみ、変更イベントを省略する必要があります。

そこにどのような遅延がありますか?

それでも、多くの機能を更新するとパフォーマンスは低下します。私は、this demoと書いています。これは、各地図上のすべてのフィーチャのジオメトリを置き換えます。私のラップトップでは、10,000個のジオメトリすべてを交換するのに約600ミリ秒かかる。その間、マップとブラウザは応答しなくなり、次回の再描画まで更新内容は表示されません。再描画の時間はズームレベルによって異なります。

  • が前の形状にされたリスナーを削除し、それのプロパティ
  • にジオメトリを追加します。設定機能のジオメトリ、それはなります

  • 変更リスナーを新しいジオメトリに追加します。
  • リスナーに変更イベントが発生したことを通知するためにchangeイベントをトリガーします。特徴のリスナーのオン

するソース、次のようになります使用する場合

  • は、空間インデックスを更新します。
  • リスナーに変更イベントが発生したことを通知するためにchangeイベントをトリガーします。

レイヤーと最終的にマップはこれらの変更を通知し、再描画をキューに入れます。

可能な最適化

あなたはよりパフォーマンスの方法で多くの機能を変更できるようにしたい場合は、私が考えることをお勧めしたい:述べたように、空間インデックス

を無効

docsでは、useSpatialIndexをfalseに設定すると、状況によってはパフォーマンスが向上することがあります。空間インデックスがないと、ソースは各フィーチャの変更で行う計算が少なくなります。ただし、索引がなければ、ソースの他の用途はパフォーマンスが低下する可能性があります。

ジオメトリを変更する代わりに、幾何学的にsetCoordinatesを使用して

それを置き換えるには、機能上のsetGeometryを使用するよりも高速です。ジオメトリインスタンスの作成全体をスキップすることができ、リスナを変更する必要はありません。これは、フィーチャがジオメトリの唯一の「所有者」である場合など、ジオメトリを変更できると想定しています。これは、質問の意図に反して小さな塊

に機能の変更を分割しようとすると

。機能を変更するのに多くの時間がかかる場合は、レンダリングをより頻繁に開始することをお勧めします。そうすれば、地図のレスポンスが向上し、ブラウザがイベントやその他の保留中のタスクを処理できるようになります。

+0

これは最善の答えかもしれません!あなたの例は、レイヤー自体ではなく、ポストレンダーマップ上にあるので、まずこれをテストしなければなりません。ポストレンダリングのレイヤーを聞くことができるかどうかは不明です。しかし、後で私はそれをチェックします。しかし、あなたがそれをテストすることができれば、私はこれを答えとしてマークします!注:私はspacialindexを使用していませんが、徹底的な答えとして、これはより精巧です。 – psyntium

関連する問題