【问题标题】:Openlayers 6.3.1 - rendering tilelayersOpenlayers 6.3.1 - 渲染 tilelayers
【发布时间】:2020-07-17 05:51:04
【问题描述】:

在 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.

我创建了一个虚拟 axample(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);
    }

}

【问题讨论】:

  • 嗨 Anmap。欢迎来到 StackOverflow。请向我们展示您需要优化的代码。 stackoverflow.com/help/minimal-reproducible-example。它可能会更容易为您提供帮助。
  • 添加了用户在问题中尝试的代码
  • 你解决过性能问题吗?我有同样的问题,我很确定它归结为渲染。您在下面的答案中的修复并没有让我变得更好。

标签: performance rendering openlayers openlayers-6


【解决方案1】:

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 图层名称会更有效。

【讨论】:

  • 我必须逐层更改图层可见性:(
  • 如果只是可见性(不是不透明度),您可以使用layer.getSource().updateParams({LAYERS : newlayerlist});
  • 对不起,但不是相同的 url,我可以尝试在 tileLoadFunction 中通过 larenames 分叉 url。但是,如果其中一项服务很慢,整个图块加载就会很慢,...,我必须渲染图块。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2023-04-10
    • 2022-10-21
    • 2020-04-14
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多