0


OpenLayers 图标加载性能优化:使用 Style 样式缓存

文章目录

一、概要

在使用 OpenLayers 为大量矢量点应用图标样式进行地图渲染时,频繁地创建 Style 对象会增加内存消耗影响渲染效率和导致图标闪烁

例如以下方法,根据不同的颜色和透明度,渲染矢量点图标:

/**
 * 获取给定要素的样式
 * @param { Feature<Geometry> } feature 矢量要素
 * @returns {Style} 要素样式数组
 */functiongetStyle(feature: Feature<Geometry>): Style {const baseColor = feature.get('color')??'rgba(0, 0, 0, 1)';// 默认颜色为黑色const opacity = feature.get('opacity')??1;// 默认透明度为1const rotation = feature.get('rotation')??0;// 默认旋转为0// 将透明度添加到颜色字符串中const color =`${baseColor.slice(0,-1)}, ${opacity})`;// 为每个要素定义样式returnnewStyle({
    image:newIcon({
      scale:1,
      src:"/img/ship.png",
      color,
      rotation,
      crossOrigin:'anonymous',})})}

测试,加载10000个数据,出现图标闪烁问题。

请添加图片描述
为优化渲染图标的性能,可以创建样式池复用 Style 对象,而不是每次都新建。以显著减少内存消耗并提高性能。


二、完整代码:渲染矢量点,使用样式缓存策略

<template><!--地图--><div ref="mapContainer"class="mapContainer" id="mapContainer"></div></template><script lang="ts" setup>import{ onMounted, shallowRef }from'vue'import{ View, Map as OLMap, Feature }from"ol"import{ fromLonLat }from'ol/proj'import TileLayer from'ol/layer/Tile'import{XYZ}from'ol/source'import{ defaults as defaultControls }from"ol/control"import{ Vector as VectorLayer }from'ol/layer'import VectorSource from'ol/source/Vector'import{ Circle as CircleStyle, Style, Icon }from"ol/style";import{ FeatureLike }from'ol/Feature'import{ Geometry }from'ol/geom'import GeoJSON from'ol/format/GeoJSON'// 改为你自己的GeoJson数据地址const pointDataURL ='./geoJson/1W'// 地图容器const mapContainer =shallowRef<HTMLDivElement>()// 地图对象const map =shallowRef<OLMap>()/**
 * @description 创建地图实例
 * @param {Document | DocumentId} target 地图容器
 * @returns 地图对象
 */constcreateMap=function(target: HTMLElement |string,): OLMap {// 创建地图const map =newOLMap({
    target,
    layers:[newTileLayer({
        source:newXYZ({
          url:"http://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=99a8ea4a53c8553f6f3c565f7ffc15ec",
          crossOrigin:'anonymous',
          wrapX:true})})],
    controls:defaultControls({
      zoom:false,// 不显示放大放小按钮
      rotate:false,// 不显示指北针控件
      attribution:false,// 不显示右下角的地图信息控件}).extend([]),
    view:newView({
      projection:'EPSG:3857',// 坐标系EPSG:4326或EPSG:3857
      zoom:6,// 打开页面时默认地图缩放级别
      maxZoom:20,
      minZoom:1,// 地图缩放最小级别
      center:fromLonLat([121.5,25]),// 需要转到墨卡托坐标系
      constrainResolution:true,// 自动缩放到距离最近的一个整数级别,因为当缩放在非整数级别时地图会糊})})return map
}/**
 * @description 新建图层(检测到同名图层直接获取)
 * @param map 地图实例
 * @param layerName 图层名
 * @param getStyle feature样式
 * @returns 
 */functiongetVectorLayer(map: OLMap, layerName: String, getStyle:Function): VectorLayer<VectorSource>{let vectorLayer = map.getLayers().getArray().find(layer => layer.get('name')=== layerName)as VectorLayer<VectorSource>;if(!vectorLayer){
    vectorLayer =newVectorLayer({
      source:newVectorSource({ wrapX:true, features:[]}),style:function(feature: FeatureLike){returngetStyle(feature)}});
    vectorLayer.set('name', layerName);
    map.addLayer(vectorLayer);}return vectorLayer;}/**
 * @description >>>>>>>> 添加矢量点(可追加数据)
 * @param { Map } map 地图对象
 * @param { string} layerName 图层名
 * @param { any } pointData 点据集合
 */functionaddPointVector(
  map: OLMap,
  layerName:string,
  pointData:any){if(!map ||!pointData){return}// 获取矢量图层let vectorLayer: VectorLayer<VectorSource>|null=getVectorLayer(map, layerName, getStyle)// 添加数据源let features =newGeoJSON({ dataProjection:'EPSG:4326', featureProjection:'EPSG:3857'}).readFeatures(pointData)
  vectorLayer?.getSource()!.addFeatures(features)}// 全局样式缓存const styleCache: Record<string, Style>={};/**
 * 获取给定要素的样式
 * @param { Feature<Geometry> } feature 矢量要素
 * @returns { Array<Style> } 要素样式数组
 */functiongetStyle(feature: Feature<Geometry>): Style {// 从要素中获取样式属性,设置默认值const baseColor = feature.get('color')??'rgba(0, 0, 0, 1)';// 默认颜色为黑色const opacity = feature.get('opacity')??1;// 默认透明度为1const rotation = feature.get('rotation')??0;// 默认旋转为0// 将透明度添加到颜色字符串中const color =`${baseColor.slice(0,-1)}, ${opacity})`;// 为单个要素定义样式const style =newStyle({
    image:newIcon({
      scale:1,
      src:"/img/ship.png",// 图片需要自己找,放在public/img内
      color,
      rotation,
      crossOrigin:'anonymous',})})// 使用唯一的缓存键存储样式const cacheKey =`${color}-${rotation}`;if(!styleCache[cacheKey]){
    styleCache[cacheKey]= style;}return styleCache[cacheKey];}onMounted(async()=>{
  map.value =createMap(mapContainer.value!);// 打开GeoJsonconst response =awaitfetch(`${pointDataURL}.json`);const point =await response.json();// 加载PointaddPointVector(map.value,'pointLayer', point)});</script><style lang="scss">
#mapContainer {
  position: absolute;
  top:0;
  z-index:0;
  width:100%;
  height:100%;}</style>

请添加图片描述

三、核心代码:使用样式池复用样式

// 全局样式缓存conststyleCache: Record<string, Style>={};/**
 * 获取给定要素的样式
 * @param { Feature<Geometry> } feature 矢量要素
 * @returns { Array<Style> } 要素样式数组
 */functiongetStyle(feature: Feature<Geometry>): Style {// 从要素中获取样式属性,设置默认值const baseColor = feature.get('color')??'rgba(0, 0, 0, 1)';// 默认颜色为黑色const opacity = feature.get('opacity')??1;// 默认透明度为1const rotation = feature.get('rotation')??0;// 默认旋转为0// 将透明度添加到颜色字符串中const color =`${baseColor.slice(0,-1)}, ${opacity})`;// 为单个要素定义样式const style =newStyle({image:newIcon({scale:1,src:"/img/ship.png",// 图片需要自己找,放在public/img内
      color,
      rotation,crossOrigin:'anonymous',})})// 使用唯一的缓存键存储样式const cacheKey =`${color}-${rotation}`;if(!styleCache[cacheKey]){
    styleCache[cacheKey]= style;}return styleCache[cacheKey];}
  • 主要思路: 1.样式函数外部初始化样式池(styleCache)对象 2.样式函数内部获取样式属性并设置默认值 3.定义样式,创建唯一缓存键 (cacheKey),根据唯一键存储在样式池中。
  • 注意事项: 1.键的唯一性:当前的缓存机制只使用颜色和旋转角度作为缓存键。如果样式属性组合更多,可增加更多的属性到 cacheKey 中,以确保唯一性。 2.尽量避免在 getStyle 中进行复杂计算,确保 getStyle 函数中只包含必要的逻辑,以减少性能开销。

四、数据说明

本文使用的矢量点数据为标准的GeoJson数据,制作工具下方自取,属性字段包括:

  • name:名称/编码,类型为 string | number
  • rotation:旋转角度,范围0~1
  • opacity:透明度,范围0~1
  • color:rgba颜色

数据样例:

{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"rotation":0.13,"name":"1500","englishType":0.07,"opacity":0.5,"color":"rgba(57, 174, 24)"},"geometry":{"coordinates":[-118.70523953338989,-1.3911765556242415],"type":"Point"}},]}

本文转载自: https://blog.csdn.net/qq_40236953/article/details/141567436
版权归原作者 無可言喻 所有, 如有侵权,请联系我们删除。

“OpenLayers 图标加载性能优化:使用 Style 样式缓存”的评论:

还没有评论