0


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

文章目录

一、概要

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

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

  1. /**
  2. * 获取给定要素的样式
  3. * @param { Feature<Geometry> } feature 矢量要素
  4. * @returns {Style} 要素样式数组
  5. */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({
  6. image:newIcon({
  7. scale:1,
  8. src:"/img/ship.png",
  9. color,
  10. rotation,
  11. crossOrigin:'anonymous',})})}

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

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


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

  1. <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>()/**
  2. * @description 创建地图实例
  3. * @param {Document | DocumentId} target 地图容器
  4. * @returns 地图对象
  5. */constcreateMap=function(target: HTMLElement |string,): OLMap {// 创建地图const map =newOLMap({
  6. target,
  7. layers:[newTileLayer({
  8. source:newXYZ({
  9. url:"http://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=99a8ea4a53c8553f6f3c565f7ffc15ec",
  10. crossOrigin:'anonymous',
  11. wrapX:true})})],
  12. controls:defaultControls({
  13. zoom:false,// 不显示放大放小按钮
  14. rotate:false,// 不显示指北针控件
  15. attribution:false,// 不显示右下角的地图信息控件}).extend([]),
  16. view:newView({
  17. projection:'EPSG:3857',// 坐标系EPSG:4326或EPSG:3857
  18. zoom:6,// 打开页面时默认地图缩放级别
  19. maxZoom:20,
  20. minZoom:1,// 地图缩放最小级别
  21. center:fromLonLat([121.5,25]),// 需要转到墨卡托坐标系
  22. constrainResolution:true,// 自动缩放到距离最近的一个整数级别,因为当缩放在非整数级别时地图会糊})})return map
  23. }/**
  24. * @description 新建图层(检测到同名图层直接获取)
  25. * @param map 地图实例
  26. * @param layerName 图层名
  27. * @param getStyle feature样式
  28. * @returns
  29. */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){
  30. vectorLayer =newVectorLayer({
  31. source:newVectorSource({ wrapX:true, features:[]}),style:function(feature: FeatureLike){returngetStyle(feature)}});
  32. vectorLayer.set('name', layerName);
  33. map.addLayer(vectorLayer);}return vectorLayer;}/**
  34. * @description >>>>>>>> 添加矢量点(可追加数据)
  35. * @param { Map } map 地图对象
  36. * @param { string} layerName 图层名
  37. * @param { any } pointData 点据集合
  38. */functionaddPointVector(
  39. map: OLMap,
  40. layerName:string,
  41. 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)
  42. vectorLayer?.getSource()!.addFeatures(features)}// 全局样式缓存const styleCache: Record<string, Style>={};/**
  43. * 获取给定要素的样式
  44. * @param { Feature<Geometry> } feature 矢量要素
  45. * @returns { Array<Style> } 要素样式数组
  46. */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({
  47. image:newIcon({
  48. scale:1,
  49. src:"/img/ship.png",// 图片需要自己找,放在public/img内
  50. color,
  51. rotation,
  52. crossOrigin:'anonymous',})})// 使用唯一的缓存键存储样式const cacheKey =`${color}-${rotation}`;if(!styleCache[cacheKey]){
  53. styleCache[cacheKey]= style;}return styleCache[cacheKey];}onMounted(async()=>{
  54. map.value =createMap(mapContainer.value!);// 打开GeoJsonconst response =awaitfetch(`${pointDataURL}.json`);const point =await response.json();// 加载PointaddPointVector(map.value,'pointLayer', point)});</script><style lang="scss">
  55. #mapContainer {
  56. position: absolute;
  57. top:0;
  58. z-index:0;
  59. width:100%;
  60. height:100%;}</style>

请添加图片描述

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

  1. // 全局样式缓存conststyleCache: Record<string, Style>={};/**
  2. * 获取给定要素的样式
  3. * @param { Feature<Geometry> } feature 矢量要素
  4. * @returns { Array<Style> } 要素样式数组
  5. */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内
  6. color,
  7. rotation,crossOrigin:'anonymous',})})// 使用唯一的缓存键存储样式const cacheKey =`${color}-${rotation}`;if(!styleCache[cacheKey]){
  8. 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颜色

数据样例:

  1. {"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 样式缓存”的评论:

还没有评论