2016-08-24 29 views
2

我正在構建一個將要素映射到描繪平面圖的圖像層(使用OL的ImageStatic層)的應用程序。每個功能都有一個svg圖標作爲樣式,並且可能會在邊緣附近具有其他svg圖標作爲「徽章」。在使用500個功能進行平移時,OpenLayers 3中的性能下降

我已經在this jsfiddle中設置了代碼的相關部分的簡化版本。

var map = new ol.Map({ 
    layers: [], 
    interactions: ol.interaction.defaults({}), 
    target: "map" 
}); 

var pixelProjection = new ol.proj.Projection({ 
    code: 'pixel', 
    units: 'pixels', 
    extent: [0, 0, 4097, 1596] 
    }), 
    // create layer 
    floorMapLayer = new ol.layer.Image({ 
    source: new ol.source.ImageStatic({ 
     url: "https://sunriverassistedliving.com/wp-content/uploads/Main-Floor-Plan.jpg", 
     imageSize: [4097, 1596], 
     projection: pixelProjection, 
     imageExtent: pixelProjection.getExtent() 
    }) 
    }), 
    // create view 
    floorMapView = new ol.View({ 
    projection: pixelProjection, 
    center: [2000, 750] || ol.extent.getCenter(pixelProjection.getExtent()), 
    zoom: 1 
    }), 
    poiSource = new ol.source.Vector({ 
    features: [] 
    }), 
    vectorLayer = new ol.layer.Vector({ 
    source: poiSource 
    }), 
    layerGroup = new ol.layer.Group({ 
    layers: [floorMapLayer, vectorLayer] 
    }); 

map.setView(floorMapView); 
map.setLayerGroup(layerGroup); 

var iconStyle = new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({ 
    anchor: [0.5, 1], 
    anchorXUnits: 'fraction', 
    anchorYUnits: 'fraction', 
    size: [25, 25], 
    imageSize: [25, 25], 
    src: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB3aWR0aD0iMjUiIGhlaWdodD0iMjUiIGlkPSJzdmczNjQ4Ij4KICA8ZGVmcyBpZD0iZGVmczM2NTAiLz4KICA8cGF0aCBkPSJNIDEyLjUxNDksNC45NmUtMDA3IEMgNS42MTE3NCw0Ljk2ZS0wMDcgMCw1LjU4MTk0MDUgMCwxMi40ODUxIEMgMCwxOS4zODgyNiA1LjYxMTc0LDI1IDEyLjUxNDksMjUgQyAxNS4yNzY5NCwyNSAxNy44MDQ4LDI0LjA3NDg5IDE5Ljg3NDg1LDIyLjU1NjYyIEwgMTIuNTQ0NywxNy4xOTMwOSBMIDUuMjE0NTQsMjIuNTg2NDEgTCA4LjA0NTI5LDEzLjk0NTE3IEwgMC42NTU1NCw4LjY3MTA0MDUgTCA5Ljc0MzczOTUsOC42NzEwNDA1IEwgMTIuNDg1MSwwLjAyOTgwMDUgTCAxNS4yODYwNSw4LjY3MTA0MDUgTCAyNC4zNDQ0NTksOC42MTE0NDA1IEwgMTcuMDE0MywxMy45MTUzOCBMIDE5Ljg3NDg1LDIyLjU1NjYyIEMgMjIuOTc4NDc5LDIwLjI4MDI4IDI1LDE2LjYyNjIyIDI1LDEyLjQ4NTEgQyAyNSw1LjU4MTk0MDUgMTkuNDE4MDYsNC45NmUtMDA3IDEyLjUxNDksNC45NmUtMDA3IHogIi8+Cjwvc3ZnPg==" 
})); 

var styleCache = {}; 

var customStyleFunctions = [ 
    function(resolution) { 
    var style = new ol.style.Style({ 
     image: new ol.style.Icon(({ 
     anchor: [1, 2], 
     anchorXUnits: 'fraction', 
     anchorYUnits: 'fraction', 
     size: [15, 15], 
     imageSize: [15, 15], 
     src: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB3aWR0aD0iMjUiIGhlaWdodD0iMjUiIGlkPSJzdmczNjQ4Ij4KICA8ZGVmcyBpZD0iZGVmczM2NTAiLz4KICA8cGF0aCBkPSJNIDEyLjUxNDksNC45NmUtMDA3IEMgNS42MTE3NCw0Ljk2ZS0wMDcgMCw1LjU4MTk0MDUgMCwxMi40ODUxIEMgMCwxOS4zODgyNiA1LjYxMTc0LDI1IDEyLjUxNDksMjUgQyAxNS4yNzY5NCwyNSAxNy44MDQ4LDI0LjA3NDg5IDE5Ljg3NDg1LDIyLjU1NjYyIEwgMTIuNTQ0NywxNy4xOTMwOSBMIDUuMjE0NTQsMjIuNTg2NDEgTCA4LjA0NTI5LDEzLjk0NTE3IEwgMC42NTU1NCw4LjY3MTA0MDUgTCA5Ljc0MzczOTUsOC42NzEwNDA1IEwgMTIuNDg1MSwwLjAyOTgwMDUgTCAxNS4yODYwNSw4LjY3MTA0MDUgTCAyNC4zNDQ0NTksOC42MTE0NDA1IEwgMTcuMDE0MywxMy45MTUzOCBMIDE5Ljg3NDg1LDIyLjU1NjYyIEMgMjIuOTc4NDc5LDIwLjI4MDI4IDI1LDE2LjYyNjIyIDI1LDEyLjQ4NTEgQyAyNSw1LjU4MTk0MDUgMTkuNDE4MDYsNC45NmUtMDA3IDEyLjUxNDksNC45NmUtMDA3IHogIi8+Cjwvc3ZnPg==" 
     })) 
    }); 
    return [style]; 
    } 
]; 

var defaultStyleFunction = function(resolution) { 
    var feature = this; 
    this.set('manuallyHidden', false); 

    if (!feature.get('selected') && (feature.get('hidden') || feature.get('manuallyHidden'))) { 

    // use hidden marker style 
    if (!styleCache.hidden) { 
     styleCache.hidden = new ol.style.Style({}); 
    } 
    return [styleCache.hidden]; 
    } 

    // draw marker normally 
    var iconSrc = iconStyle.getSrc(); 
    if (!styleCache[iconSrc]) { 
    styleCache[iconSrc] = new ol.style.Style({ 
     image: iconStyle, 
    }); 
    } 

    var styles = [styleCache[iconSrc]]; 

    // add styles from registered overlay style functions 
    for (var i = 0; i < customStyleFunctions.length; i++) { 
    //console.log(customStyleFunctions[i]); 
    styles = styles.concat(customStyleFunctions[i](resolution)); 
    } 

    return styles; 
}; 

for (var i = 0; i < 500; i++) { 
    var posX = Math.random() * 4097; 
    var posY = Math.random() * 1596; 
    var feature = new ol.Feature({ 
    geometry: new ol.geom.Point([posX, posY]), 
    }); 
    feature.setStyle(defaultStyleFunction); 

    poiSource.addFeature(feature); 
} 

這裏有500個功能,每個都有一個徽章。平移地圖感覺不舒服,Chrome中的時間軸注意到幀頻下降到5fps左右。

Chrome Timeline

這仍然是那種可用,但在我的實際應用情況差的很遠,只使用大約100個功能,每1-2個徽章,即使完全凍結窗口。我還沒有能夠縮小爲什麼我的真實應用程序的響應速度比這個演示程序的響應速度慢的原因,但是剖析器並沒有注意到任何其他正在運行的代碼,而是OpenLayers中的渲染和GPU正忙着喘氣。不過,我的真實應用測試中的底層圖像要大得多。大約10000x7000像素(jsfiddle一個大約是4000x1600像素)。這當然會產生巨大的畫布,需要重新繪製資源。

我想知道在OpenLayers中是否有其他任何性能提升,我可以使用這些提升地圖的響應速度?我在2011年末的13英寸MacBook Pro上使用最新的Google Chrome/Firefox版本3.15.1。

+0

你不這麼做。 https://cdn.rawgit.com/ca0v/ol3-lab/v3.17.1/rawgit.html?run=labs/style-lab&debug=1可以有500個複雜的樣式,並且可以在我的非常慢的筆記本電腦上平滑地(在Chrome中)呈現。 –

回答

4

靜態圖像層不應該是一個問題。但是,您正在以非常低效的方式使用矢量圖層的樣式函數。每次調用樣式函數時都不要創建新的樣式實例。相反,在外面創建樣式,只讓樣式函數返回它。此外,最好在圖層上設置一個樣式函數,而不是在每個要素上設置一個。

+0

謝謝。當圖標或多或少是靜態的時候,在圖層上而不是圖案上設置樣式似乎是可行的。但這些圖標變化很大,可能有許多不同的配置(圖標+徽章組合)。爲每個配置創建自己的圖層似乎不切實際,而不是在功能本身上設置樣式。或者我錯過了什麼?我所做的一個優化是在存儲樣式對象的地方有一個「樣式緩存」,而不是在配置更改時創建新的樣式對象。我現在注意到這種做法不適用於徽章,這是我能做的一件事。 –

+0

另外,當我移動地圖上的功能時,我希望徽章隨功能一起移動。如果同一類型的所有圖標(功能圖標和徽章圖標)都顯示在其自己的圖層上,甚至有可能嗎? –

+1

您可能想要熟悉OpenLayers中的樣式函數。這些屬性在矢量圖層上設置爲屬性,並在渲染時針對每個要素調用。樣式函數以特徵和視圖分辨率作爲參數來調用。您可以根據那裏的要素屬性動態返回不同的樣式。 – ahocevar

2

您可以使用webgl作爲渲染選項,只需將renderer: 'webgl'添加到您的地圖構造函數中即可。 我在這裏修改了您的示例,甚至使用了10,000分:https://jsfiddle.net/qmpd04y5/ 不幸的是,由於交叉源請求失敗,我不得不移除背景底圖層,因此當Web應用程序在服務器上運行時,這當然可以重新添加背景圖像具有相同的原點。

如果webgl不是一個選項,您還可以設置一個WMS系統將圖像預渲染爲平鋪圖像,這可以根據您的服務器提高性能。使用WMS的優點是,根據客戶端,您永遠不會遇到可伸縮性問題,因爲客戶端只會加載圖像切片。

+0

謝謝!帶瓦片圖像的WMS系統是否意味着這些功能是靜態的,非交互式的?我需要這些功能是可點擊的,並且他們使用的圖標和徽章需要根據來自websocket連接的信息動態更改。 –

+0

是的,顯示的功能起初是靜態的和非交互式的,但是有一些選項可以使它們變成動態的。 1.當您的縮放級別足夠高以免出現輸入延遲時,將圖層從WMS圖層切換到矢量要素圖層。 2.按照此處所述添加要素選擇:http://gis.stackexchange.com/questions/151979/ol3-how-to-select-features-of-a-wms-layer並更新切片,以便選擇也可見。 3.添加一個額外的圖層,當它們被選中時將這些要素加載到OpenLayers中。 –

+0

看起來webgl渲染器並不像canvas那樣清晰。當使用OSM瓷磚作爲背景時,它也顯得有些呆滯(是的,我也在使用這些瓷磚)。由於它在演示中運行良好,因此我認爲可以在代碼中進行優化,而不僅僅是在畫布渲染中進行優化。 –