Openlayers 6.3.1-渲染图块

时间:2020-07-17 05:51:04

标签: performance rendering openlayers openlayers-6

在Openlayers 6中,每个图层都有一个独立的渲染器(以前,所有图层渲染都是由单个地图渲染器管理的,并且取决于单个渲染策略-https://openlayers.org/workshop/en/webgl/meteorites.html)。在我的项目中,我有20多个TileLayers(TileWMS),并且加载,平移,滚动性能比openlayers 5差。我可以设置渲染策略吗?如何提高性能?

图块加载速度很快,但是(在加载图块之后)在地图上平移很慢。 GPU使用率不是很严格(低于30%)

Angular 9项目,服务类中的逻辑:

@Injectable({
    providedIn: 'root'
})
export class EMap {

    private eMap: OlMap;
    
    public createMapObject(): void {
        this.eMap = new OlMap({
            layers: [],
            view: new View({
                projection,
                resolutions: resolutionsArray,
                constrainResolution: true,
                enableRotation: false
            }),
            controls: defaultControls({
                rotate: false,
                attribution: false,
                zoom: false
            }).extend([
                mousePositionControl,
                scalelineControl
            ])
        });
    }
    
    public initMap(center: Coordinate, zoom: number, target: string): void {
        this.eMap.getView().setCenter(center);
        this.eMap.getView().setZoom(zoom);
        this.eMap.setTarget(target);
    }

    public addLayer(layer: TileLayer | ImageLayer | VectorLayer): void {
        this.eMap.addLayer(layer);
    }
}

@Injectable({
    providedIn: 'root'
})
export class EMapSupportlayers extends EMapNetworklayers {

    constructor(private readonly eMap: EMap) {}
    
    public addTilelayer(networklayerInfo: NetworklayerInfo): void {

        const layer: TileLayer = this.createTileLayer(tileLayerInitValues);
        this.eMap.addLayer(layer);
    }

    private createTileLayer(tileLayerInitValues: TileLayerInitValues): TileLayer {      
        const tileGrid: TileGrid = new TileGrid({
                extent: tileLayerInitValues.tileGridExtent,
                resolutions: tileLayerInitValues.resolutions,
                tileSize: tileLayerInitValues.tileSize
            });

        const source = new TileWMS({
            url: tileLayerInitValues.url,
            params: {
                LAYERS: tileLayerInitValues.layerName,
                FORMAT: tileLayerInitValues.layerFormat
            },
            tileLoadFunction: (image: any, src: string) => this.customLoader(image, src),
            tileGrid
        });

        return new TileLayer({
            visible: tileLayerInitValues.visible,
            maxZoom: tileLayerInitValues.maxZoom,
            minZoom: ttileLayerInitValues.minZoom,
            source,
            zIndex: tileLayerInitValues.zindex
        });
    }
    
    private async customLoader(tile: any, sourceUrl: string): Promise<void> {

        const response = await fetch(sourceUrl, {
            method: 'POST',
            credentials: 'include',
            headers: new Headers({
                Authorization: `Bearer ${...}`
            }),
            body: requestBody ? requestBody : null
        });

        const blob = await response.blob();
        tile.getImage().src = URL.createObjectURL(blob);
    }
}

--- 07.19。

我创建了一个虚拟轴示例(Angular9,Openlayers 6.3.1): 图层图块正在快速加载。在小屏幕上,平移速度很快,但在大屏幕上,平移速度很慢(在加载和缓存图块之后)。在openlayers 5中,性能更好。

import { AfterViewInit, Component } from '@angular/core';
import TileLayer from 'ol/layer/Tile';
import Map from 'ol/Map';
import { OSM } from 'ol/source';
import View from 'ol/View';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {

    ngAfterViewInit(): void {

        const mapElement = document.createElement('div');
        mapElement.style.cssText = 'position:absolute;width:100%;height:100%';

        const layers = [];

        for (let i = 0; i < 30; ++i) {
            const layer = new TileLayer({
                source: new OSM(),
                // className: 'layer' + i => create own canvas by layers, same performance
            });
            layer.setOpacity(0.03);
            layers.push(layer);
        }

        const map = new Map({
            layers,
            view: new View({
                center: [0, 0],
                zoom: 1
            })
        });

        document.body.appendChild(mapElement);
        map.setTarget(mapElement);
    }

}

2 个答案:

答案 0 :(得分:0)

URL.createObjectURL可能会导致内存泄漏,请尝试

    const blob = await response.blob();
    const objectURL = URL.createObjectURL(blob)
    tile.getImage().onload = function(){
      URL.revokeObjectURL(objectURL);
    };
    tile.getImage().src = objectURL;

您的任何图层还使用相同的WMS URL和不同的WMS layerName吗?将它们组合成单个OpenLayers层会更有效,并在LAYERS参数中列出WMS层名称。

答案 1 :(得分:0)

我找到了一个解决方案,虽然不完美,但是性能更好。

map.on('movestart', () => {
    layers.forEach(layer => {
        layer.setExtent(map.getView().calculateExtent());
    });
});

map.on('moveend', () => {
    layers.forEach(layer => {
        layer.setExtent(undefined);
    });
});