OpenLayers:封装Overlay的方法

news2025/5/11 13:39:04

平时在使用OpenLayers的Overlay时常感觉不便,于是最近我便封装了一些Overlay增删改查的方法,以提高可用性。这边文章中我会介绍我封装的方法,同时记录这个过程中踩的一些坑。

添加Overlay

/**
 * @abstract 添加overlay
 * @param {*} map
 * @param {object} options overlay的配置项
 * @param {string} options.id overlay的id,可以用来唯一标识overlay
 * @param {string} options.groupId overlay的组名,可以用来批量操作overlay
 * @param {boolean} options.visibility overlay的初始可见性
 * options中的其它参数参考 ol/Overlay的构造函数参数
 */
export const addOverlay = (map, options) => {
   let {
    groupId = "default",
    positioning = "center-center",
    visibility = true,
    element,
    ...other
  } = options;

  // 将DOMstring转换为DOM元素
  if (!(element instanceof HTMLElement)) {
    const container = document.createElement("div");
    container.innerHTML = element;
    element = container.firstChild;
  }

  // 创建overlay
  const overlay = new Overlay({
    element,
    positioning,
    ...other,
  });

  // 设置额外的属性
  overlay.setProperties({
    groupId,
    visibility,
  });

  // 设置初始的可见性
  overlay.on("change:map", () => {
    if (!visibility) {
      setTimeout(() => {
        overlay.getElement().parentElement.style.display = "none";
      }, 0);
    }
  });

  // 添加到地图
  map.addOverlay(overlay);
};

addOverlay方法的特别之处

我封装的添加Overlay的方法,主要的改造是三个地方。

第一,对Overlay的element属性做了一个封装。

在我第一次使用Overlay的时候我就犯了一个错误,我给element属性传递了一个DOMString(比如`<div class="test-overlay pink">粉色overlay</div>`),结果就出现了类似于下面的报错。这是因为Overlay的element属性只能接收一个DOM元素。

现在经过我的封装后,我的addOverlay方法允许传入的element属性是一个DOMString

第二,给Overlay添加一些额外的属性,这些属性会在后续帮助我去实现一些对Overlay的操作。

  // 设置额外的属性
  overlay.setProperties({
    groupId,
    visibility,
  });

第三,给Overlay设置了初始的可见性,如果传入的visibility参数为false,就会暂时先将overlay隐藏。(我还考虑后续或许可以通过这个来实现popup)

// 设置初始的可见性
overlay.on("change:map", () => {
  if (!visibility) {
    setTimeout(() => {
      overlay.getElement().parentElement.style.display = "none";
    }, 0);
  }
});

查询Overlay

/**
 * @abstract 查找overlay
 * @param {*} map
 * @param {object} condition 筛选条件
 * @param {string} condition.id overlay的id筛选需要操作的overlay
 * @param {string} condition.groupId overlay的groupId筛选需要操作的overlay
 * @param {function} condition.condition 自定义条件函数,筛选需要操作的overlay,返回true则操作,false则忽略
 * @returns  {Array} 符合条件的overlay数组
 */
export const findOverlay = (map, { id, groupId, condition }) => {
  const targetOverlays = [];
  const overlays = map.getOverlays().getArray();

  overlays.forEach(overlay => {
    const groupId_ = overlay.get("groupId");
    const id_ = overlay.getId();

    if (id) {
      if (id_ === id) {
        targetOverlays.push(overlay);
      }
    }

    if (groupId) {
      if (groupId_ === groupId) {
        targetOverlays.push(overlay);
      }
    }

    if (condition) {
      if (condition(overlay, id_, groupId_, overlays)) {
        targetOverlays.push(overlay);
      }
    }
  });

  return targetOverlays;
};

findOverlay支持的查询方式

我设计的查找Overlay的方法findOverlay支持通过三种方式进行查找:

  1. 通过id查找,这个id是创建 Overlay时的参数(我建议在创建overlay时最好都要添加这个参数)
// 查找id为'overlay-1'的overlay
findOverlay( map , { id : 'overlay-1' })
  1. 通过groupId查找,这个是我在addOverlay方法中添加的一个额外属性,我的计划是通过groupId实现对Overlay的分组管理,可以同时去操作一组的Overlay。
// 查找所有groupId 为 stationTooltip 的overlay
findOverlay( map , { groupId : 'stationTooltip' })
  1. 通过一个筛选函数condition来进行查找,这个就类似于js中Array.prototype.find()方法。我会为地图中绑定的每个overlay都调用condition方法,若condition方法返回true则将Overlay返回,若返回false则Overlay会被忽略。

  condition方法将会接收到四个参数:

    • overlay,当前的overlay对象;
    • id,当前的overlay对象的id;
    • groupId,当前overlay对象的groupId;
    • overlays,地图中的所有overlay对象组成的数组
// 查找所有groupId 为 stationTooltip 的overlay
findOverlay( map , { condition:(overlay , id , groupId , overlays)=> groupId == "stationTooltip" })

最后,注意findOverlay方法返回一个包含所有符合条件的Overlay对象的数组。

删除Overlay

/**
 * @abstract 移除overlay
 * @param {*} map
 * @param {object} condition 筛选条件
 * @param {string} condition.id overlay的id筛选需要操作的overlay
 * @param {string} condition.groupId overlay的groupId筛选需要操作的overlay
 * @param {function} condition.condition 自定义条件函数,筛选需要操作的overlay,返回true则操作,false则忽略
 */
export const removeOverlay = (map, { id, groupId, condition }) => {
  const targetOverlays = findOverlay(map, { id, groupId, condition });

  targetOverlays.forEach(overlay => {
    map.removeOverlay(overlay);
  });
};

/**
 *@abstract 清除所有overlay
 * @param {*} map
 */
export const clearOverlay = map => {
  const overlays = map.getOverlays();
  overlays.clear();
};

我封装了两个删除Overlay的方法removeOverlayclearOverlay,前者删除符合条件的Overlay,后者清空地图中的所有Overlay。

错误的删除方式

之前我在网上看到下面的这种删除Overlay的方式。也就是边遍历边删除,这种方法是错误的。会有删除不尽的问题。

  const overlays = map.getOverlays();
  overlays.forEach((overlay, index) => {
    if (overlay.getId() === id) {
      overlays.removeAt(index);
    }
  });

正确的写法是先通过遍历将想要删除Overlay收集到一个数组中,然后再循环数组进行删除.。

  const overlays = map.getOverlays();

  const targetOverlays = []
  overlays.forEach((overlay, index) => {
    if (overlay.getId() === id) {
      targetOverlays.push(overlay)
    }
  });

  targetOverlays.forEach((overlay)=>{
    map.removeOverlay(overlay) 
  })

显示/隐藏Overlay

/**
 * @abstract 设置overlay的可见性
 * @param {*} map
 * @param {object} condition 筛选条件
 * @param {string} condition.id overlay的id筛选需要操作的overlay
 * @param {string} condition.groupId overlay的groupId筛选需要操作的overlay
 * @param {function} condition.condition 自定义条件函数,筛选需要操作的overlay,返回true则操作,false则忽略
 * @param {boolean} visible 要设置的可见性
 */
export const setOverlayVisibility = (
  map,
  { id, groupId, condition, visible }
) => {
  const targetOverlays = findOverlay(map, { id, groupId, condition });

  targetOverlays.forEach(overlay => {
    overlay.setProperties({
      visibility: visible,
    });

    const element = overlay.getElement();
    element.parentElement.style.display = visible ? "flex" : "none";
  });
};

/**
 * @abstract 切换overlay的可见性
 * @param {*} map
 * @param {object} condition 筛选条件
 * @param {string} condition.id overlay的id筛选需要操作的overlay
 * @param {string} condition.groupId overlay的groupId筛选需要操作的overlay
 * @param {function} condition.condition 自定义条件函数,筛选需要操作的overlay,返回true则操作,false则忽略
 */
export const toggleOverlayVisibility = (map, { id, groupId, condition }) => {
  const targetOverlays = findOverlay(map, { id, groupId, condition });

  targetOverlays.forEach(overlay => {
    const newVisibility = !overlay.get("visibility");
    overlay.setProperties({
      visibility: newVisibility,
    });

    const element = overlay.getElement();
    element.parentElement.style.display = newVisibility ? "flex" : "none";
  });
};

显示/隐藏Overlay的方法我也封装了两个 setOverlayVisibility用于手动的设置显隐,toggleOverlayVisibility用于自动设置显隐。

隐藏Overlay的方法是去修改Overlay的element的父元素的display。我们在创建Overlay的时候传入的element实际上会被用另一个元素包装起来,这个元素(默认class为ol-overlay-container ol-selectable的元素)才是Overlay的根元素。

参考资料

  1. OpenLayers v10.5.0 API - Class: Overlay
  2. OpenLayers v10.5.0 API - Class: Collection
  3. OpenLayers之 OverLay问题汇总_openlayers overlay zindex-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2327633.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件重构与项目进度的矛盾如何解决

软件重构与项目进度之间的矛盾可以通过明确重构目标与范围、采用渐进式重构策略、优化项目管理流程、提高团队沟通效率、建立重构意识文化等方式解决。其中&#xff0c;采用渐进式重构策略尤为关键。渐进式重构是指在日常开发过程中&#xff0c;以小步骤持续进行重构&#xff0…

数智化时代下开源AI大模型驱动的新型商业生态构建——基于AI智能名片与S2B2C商城小程序的融合创新研究

摘要 数字技术的指数级发展推动物理世界向数智化网状结构加速转型&#xff0c;传统商业逻辑面临系统性重构。本文以"开源AI大模型AI智能名片S2B2C商城小程序"为研究主体&#xff0c;采用案例分析与技术验证相结合的方法&#xff0c;揭示技术融合对商业生态的重塑机制…

Spring Cloud Alibaba 技术全景与实战指南

简介&#xff1a; Spring Cloud Alibaba 是阿里巴巴开源的微服务解决方案&#xff0c;基于 Spring Cloud 标准构建&#xff0c;提供了一站式分布式系统开发能力。它深度整合阿里云生态组件&#xff0c;为企业级微服务架构提供高可用、高性能的技术支撑。 核心特性 全栈微服务能…

回归预测 | Matlab实现NRBO-Transformer-BiLSTM多输入单输出回归预测

回归预测 | Matlab实现NRBO-Transformer-BiLSTM多输入单输出回归预测 目录 回归预测 | Matlab实现NRBO-Transformer-BiLSTM多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.【JCR一区级】Matlab实现NRBO-Transformer-BiLSTM多变量回归预测&#xf…

Git的基础使用方法

本文最终功能&#xff1a; 1.从终端直接传输代码给仓库 2.用终端从仓库克隆文件 基本概念 我们先来理解下 Git 工作区、暂存区和版本库概念&#xff1a; 工作区&#xff1a;就是你在电脑里能看到的目录。 暂存区&#xff1a;英文叫 stage 或 index。一般存放在 .git 目录下的…

Java常用异步方式总结

使用建议 完整代码见https://gitee.com/pinetree-cpu/parent-demon 提供了postMan调试json文件于security-demo/src/main/resources/test_file/java-async.postman_collection.json 可导入postMan中进行调试 Java异步方式以及使用场景 继承Thread类 新建三个类继承Thread&…

苍穹外卖day12

课程内容 工作台 Apache POI 导出运营数据Excel报表 功能实现&#xff1a;工作台、数据导出 工作台效果图&#xff1a; 数据导出效果图&#xff1a; 在数据统计页面点击数据导出&#xff1a;生成Excel报表 1. 工作台 1.1 需求分析和设计 1.1.1 产品原型 工作台是系统运…

【Feign】⭐️使用 openFeign 时传递 MultipartFile 类型的参数参考

&#x1f4a5;&#x1f4a5;✈️✈️欢迎阅读本文章❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;本篇文章阅读大约耗时三分钟。 ⛳️motto&#xff1a;不积跬步、无以千里 &#x1f4cb;&#x1f4cb;&#x1f4cb;本文目录如下&#xff1a;&#x1f381;&#x1f381;&a…

Linux中动静态库的制作

1.什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复⽤的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个⼈的代码都从零开始&#xff0c;因此库的存在意义非同寻常。 本质上来说库是⼀种可执⾏代码的⼆进制形式&#xff0c;可以被操作系统…

forms实现连连看

说明&#xff1a; forms实现连连看 效果图&#xff1a; step1:C:\Users\wangrusheng\RiderProjects\WinFormsApp2\WinFormsApp2\Form1.cs using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms;namespace …

鸿蒙开发踩坑记录 - 2024S2

wrapBuilder如果想View和ObservedV2做绑定 必须要用 ComponentV2 Param 和 区别 退出两层循环 Builder的传入的参数及时是Trace修饰的也无法刷新组件 折叠屏展开后键盘无法点击 vm是公用的&#xff0c;组件生命周期问题导致 监听键盘高度变化失效 原因&#xff1a;分享面…

0基础入门scrapy 框架,获取豆瓣top250存入mysql

一、基础教程 创建项目命令 scrapy startproject mySpider --项目名称 创建爬虫文件 scrapy genspider itcast "itcast.cn" --自动生成 itcast.py 文件 爬虫名称 爬虫网址 运行爬虫 scrapy crawl baidu(爬虫名&#xff09; 使用终端运行太麻烦了&#xff0c;而且…

鸿蒙NEXT小游戏开发:井字棋

1. 引言 井字棋是一款经典的两人对战游戏&#xff0c;简单易懂&#xff0c;适合各个年龄段的玩家。本文将介绍如何使用鸿蒙NEXT框架开发一个井字棋游戏&#xff0c;涵盖游戏逻辑、界面设计及AI对战功能。 2. 开发环境准备 电脑系统&#xff1a;windows 10 开发工具&#xff1a;…

deep-sync开源程序插件导出您的 DeepSeek 与 public 聊天

一、软件介绍 文末提供下载 deep-sync开源程序插件导出您的 DeepSeek 与 public 聊天&#xff0c;这是一个浏览器扩展&#xff0c;它允许用户公开、私下分享他们的聊天对话&#xff0c;并使用密码或过期链接来增强 Deepseek Web UI。该扩展程序在 Deepseek 界面中添加了一个 “…

4. 理解Prompt Engineering:如何让模型听懂你的需求

引言:当模型变成“实习生” 想象一下,你新招的实习生总把“帮我写份报告”理解为“做PPT”或“整理数据表”——这正是开发者与大模型对话的日常困境。某金融公司优化提示词后,合同审查准确率从72%飙升至94%。本文将用3个核心法则+5个行业案例,教你用Prompt Engineering让…

网络编程—网络概念

目录 1 网络分类 1.1 局域网 1.2 广域网 2 常见网络概念 2.1 交换机 2.2 路由器 2.3 集线器 2.4 IP地址 2.5 端口号 2.6 协议 3 网络协议模型 3.1 OSI七层模型 3.2 TCP/IP五层模型 3.3 每层中常见的协议和作用 3.3.1 应用层 3.3.2 传输层 3.3.3 网络层 3.3.4…

SELinux

一、selinux技术详解 SELinux 概述 SELinux&#xff0c;即 Security-Enhanced Linux&#xff0c;意为安全强化的 Linux&#xff0c;由美国国家安全局&#xff08;NSA&#xff09;主导开发。开发初衷是防止系统资源被误用。在 Linux 系统中&#xff0c;系统资源的访问均通过程…

ES6对函数参数的新设计

ES6 对函数参数进行了新的设计&#xff0c;主要添加了默认参数、不定参数和扩展参数&#xff1a; 不定参数和扩展参数可以认为恰好是相反的两个模式&#xff0c;不定参数是使用数组来表示多个参数&#xff0c;扩展参数则是将多个参数映射到一个数组。 需要注意&#xff1a;不定…

LLaMA Factory微调后的大模型在vLLM框架中对齐对话模版

LLaMA Factory微调后的大模型Chat对话效果&#xff0c;与该模型使用vLLM推理架构中的对话效果&#xff0c;可能会出现不一致的情况。 下图是LLaMA Factory中的Chat的对话 下图是vLLM中的对话效果。 模型回答不稳定&#xff1a;有一半是对的&#xff0c;有一半是无关的。 1、未…

群体智能优化算法-鹈鹕优化算法(Pelican Optimization Algorithm, POA,含Matlab源代码)

摘要 鹈鹕优化算法&#xff08;Pelican Optimization Algorithm, POA&#xff09;是一种灵感来自自然界鹈鹕觅食行为的元启发式优化算法。POA 模拟鹈鹕捕食的两个主要阶段&#xff1a;探索阶段和开发阶段。通过模拟鹈鹕追捕猎物的动态行为&#xff0c;该算法在全局探索和局部开…