当前位置: 首页 > news >正文

Vue2+OpenLayers给标点Feature添加信息窗体(提供Gitee源码)

目录

一、案例截图

二、安装OpenLayers库

三、代码实现

3.1、信息窗体DOM元素

3.2、创建Overlay

3.3、创建一个点

3.4、给点初始化点击事件

3.5、完整代码

四、Gitee源码


一、案例截图

二、安装OpenLayers库

npm install ol

三、代码实现

初始化变量:

  data() {return {map:null,overLay:null,//所有点信息都放在这个图层pointLayer: new VectorLayer({source: new VectorSource(),}),}},

3.1、信息窗体DOM元素

关键代码:

  <div><div id="map-container"></div><div id="popup-box" class="popup-box"><button id="close-button" class="close-button">&times;</button><div id="popup-content" class="popup-content"></div></div></div>

css样式:

<style scoped>#map-container {width: 100%;height: 100vh;
}
.popup-box {background: rgba(255, 255, 255, 0.95);border: 1px solid #ccc;border-radius: 8px;padding: 20px;z-index: 1000;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);transition: all 0.3s ease;max-width: 300px;font-family: 'Arial', sans-serif;position: absolute;transform: translate(-50%, -100%); /* 使弹出框上移并居中 */
}/* 添加箭头样式 */
.popup-box::after {content: "";position: absolute;top: 100%; /* 箭头位于弹出框的底部 */left: 50%; /* 箭头横向居中 */margin-left: -6px; /* 调整箭头与弹出框的间距 */border-width: 6px; /* 箭头的大小 */border-style: solid;border-color: rgba(255, 255, 255, 0.95) transparent transparent transparent; /* 箭头的颜色 */
}.close-button {background: none;color: gray;border: none;font-size: 20px;position: absolute;top: 10px;right: 10px;cursor: pointer;
}.popup-content {width: 240px;margin-top: 10px;font-size: 16px;line-height: 1.5;
}
</style>

3.2、创建Overlay

覆盖物(Overlay)是用于在地图上显示额外的HTML元素,如弹出窗口、信息框、控件等的层。与图层不同,覆盖物不直接渲染地理要素,而是用于展示与地图位置相关的HTML内容。

element (必需):指定用于作为Overlay内容的DOM元素。通常是一个HTML元素,例如div,作为弹出框或工具提示等。

autoPan (可选) :boolean 或 { animation: { duration: number } } 默认值:false,如果设置为 true,地图将在Overlay显示时自动平移,以确保Overlay的位置始终在视图范围内。如果设置为对象,可以自定义平移时的动画效果。例如,设置动画持续时间。

position (可选) :[number, number](坐标数组) 默认值:undefined,初始化时设置Overlay的位置,指定为地图坐标系中的坐标。如果未指定,Overlay不会显示。

stopEvent (可选) :默认值:true,确定Overlay的点击事件是否会停止事件传播。如果设置为 false,点击 Overlay 的内容不会阻止点击事件向下传播到地图层。

offset (可选) :默认值:[0, 0] 说明:Overlay内容相对于指定位置的偏移量,用于微调Overlay的显示位置。例如,可以通过提供负值来向上或向左移动Overlay。

关键代码:

let popupBox = document.getElementById('popup-box');
let closeButton = document.getElementById('close-button');
//用于显示详情页面的窗口(根据经纬度来的,位置不固定)
this.overlay = new Overlay({element: popupBox,autoPan: {animation: {duration: 250,},},offset:[0,-20],
});
this.map.addOverlay(this.overlay);
// 关闭弹出框的事件处理
let _that = this;
closeButton.addEventListener('click', () => {_that.overlay.setPosition(undefined); // 关闭弹出框
});

3.3、创建一个点

关键代码:

/*** 根据经纬度坐标添加自定义图标 支持base64*/
addPoints(coordinate) {// 创建feature要素,一个feature就是一个点坐标信息let feature = new Feature({geometry: new Point(coordinate),});// 设置要素的图标feature.setStyle(new Style({// 设置图片效果image: new Icon({src: 'http://api.tianditu.gov.cn/img/map/markerA.png',// anchor: [0.5, 0.5],scale: 1,}),}),);return feature;
},

将其添加到图层上,再将图层添加到地图上。

let feature = this.addPoints([118.958412, 32.119130]);
this.pointLayer.getSource().addFeature(feature);
this.map.addLayer(this.pointLayer);feature = this.addPoints([118.948627, 32.120428]);
this.pointLayer.getSource().addFeature(feature);

3.4、给点初始化点击事件

思路就是遍历地图上所有图层中的Feature,并为它们添加点击事件。

关键代码:

initPointEvent(){let _that = this;//给点初始化点击事件this.map.on("singleclick", (e) => {let pixel = this.map.getEventPixel(e.originalEvent);let feature = this.map.forEachFeatureAtPixel(pixel, function(feature) { return feature; });if(feature){// 获取 Feature 的几何体const geometry = feature.getGeometry();// 获取坐标const coordinates = geometry.getCoordinates();// 更新 Overlay 位置_that.overlay.setPosition(coordinates);_that.overlay.getElement().style.display = 'block';let popupContent = document.getElementById('popup-content');popupContent.innerHTML = `<div>经度:${coordinates[0]}</div><div>纬度:${coordinates[1]}</div>`;}});
}

3.5、完整代码

<template><div><div id="map-container"></div><div id="popup-box" class="popup-box"><button id="close-button" class="close-button">&times;</button><div id="popup-content" class="popup-content"></div></div></div>
</template>
<script>
import {Feature, Map, View} from 'ol'
import { Tile as TileLayer } from 'ol/layer'
import { get } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent'
import { WMTS } from 'ol/source'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { defaults as defaultControls} from 'ol/control';
import Overlay from 'ol/Overlay';
import {Point} from "ol/geom";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import {Icon, Style} from "ol/style";export const projection = get("EPSG:4326");
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 0; z < 19; ++z) {resolutions[z] = size / Math.pow(2, z);
}export default {data() {return {map:null,overLay:null,//所有点信息都放在这个图层pointLayer: new VectorLayer({source: new VectorSource(),}),}},mounted(){this.initMap() // 加载矢量底图},methods:{initMap() {const KEY = '你申请的KEY'this.map = new Map({target: 'map-container',layers: [// 底图new TileLayer({source: new WMTS({url: `http://t{0-6}.tianditu.com/vec_c/wmts?tk=${KEY}`,layer: 'vec', // 矢量底图matrixSet: 'c', // c: 经纬度投影 w: 球面墨卡托投影style: "default",crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加format: "tiles", //请求的图层格式,这里指定为瓦片格式wrapX: true, // 允许地图在 X 方向重复(环绕)tileGrid: new WMTSTileGrid({origin: getTopLeft(projectionExtent),resolutions: resolutions,matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']})})}),// 标注new TileLayer({source: new WMTS({url: `http://t{0-6}.tianditu.com/cva_c/wmts?tk=${KEY}`,layer: 'cva', //矢量注记matrixSet: 'c',style: "default",crossOrigin: 'anonymous',format: "tiles",wrapX: true,tileGrid: new WMTSTileGrid({origin: getTopLeft(projectionExtent),resolutions: resolutions,matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']})})})],view: new View({center: [118.958366,32.119577],projection: projection,zoom: 12,maxZoom: 17,minZoom: 1}),//加载控件到地图容器中controls: defaultControls({zoom: false,rotate: false,attribution: false})});let popupBox = document.getElementById('popup-box');let closeButton = document.getElementById('close-button');//用于显示详情页面的窗口(根据经纬度来的,位置不固定)this.overlay = new Overlay({element: popupBox,autoPan: {animation: {duration: 250,},},offset:[0,-20],});this.map.addOverlay(this.overlay);// 关闭弹出框的事件处理let _that = this;closeButton.addEventListener('click', () => {_that.overlay.setPosition(undefined); // 关闭弹出框});let feature = this.addPoints([118.958412, 32.119130]);this.pointLayer.getSource().addFeature(feature);this.map.addLayer(this.pointLayer);feature = this.addPoints([118.948627, 32.120428]);this.pointLayer.getSource().addFeature(feature);this.initPointEvent();},/*** 根据经纬度坐标添加自定义图标 支持base64*/addPoints(coordinate) {// 创建feature要素,一个feature就是一个点坐标信息let feature = new Feature({geometry: new Point(coordinate),});// 设置要素的图标feature.setStyle(new Style({// 设置图片效果image: new Icon({src: 'http://api.tianditu.gov.cn/img/map/markerA.png',// anchor: [0.5, 0.5],scale: 1,}),}),);return feature;},initPointEvent(){let _that = this;//给点初始化点击事件this.map.on("singleclick", (e) => {let pixel = this.map.getEventPixel(e.originalEvent);let feature = this.map.forEachFeatureAtPixel(pixel, function(feature) { return feature; });if(feature){// 获取 Feature 的几何体const geometry = feature.getGeometry();// 获取坐标const coordinates = geometry.getCoordinates();// 更新 Overlay 位置_that.overlay.setPosition(coordinates);_that.overlay.getElement().style.display = 'block';let popupContent = document.getElementById('popup-content');popupContent.innerHTML = `<div>经度:${coordinates[0]}</div><div>纬度:${coordinates[1]}</div>`;}});}}
}
</script>
<style scoped>#map-container {width: 100%;height: 100vh;
}
.popup-box {background: rgba(255, 255, 255, 0.95);border: 1px solid #ccc;border-radius: 8px;padding: 20px;z-index: 1000;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);transition: all 0.3s ease;max-width: 300px;font-family: 'Arial', sans-serif;position: absolute;transform: translate(-50%, -100%); /* 使弹出框上移并居中 */
}/* 添加箭头样式 */
.popup-box::after {content: "";position: absolute;top: 100%; /* 箭头位于弹出框的底部 */left: 50%; /* 箭头横向居中 */margin-left: -6px; /* 调整箭头与弹出框的间距 */border-width: 6px; /* 箭头的大小 */border-style: solid;border-color: rgba(255, 255, 255, 0.95) transparent transparent transparent; /* 箭头的颜色 */
}.close-button {background: none;color: gray;border: none;font-size: 20px;position: absolute;top: 10px;right: 10px;cursor: pointer;
}.popup-content {width: 240px;margin-top: 10px;font-size: 16px;line-height: 1.5;
}
</style>

四、Gitee源码

地址: Vue2+OpenLayers给标点Feature添加信息窗体

相关文章:

Vue2+OpenLayers给标点Feature添加信息窗体(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 3.1、信息窗体DOM元素 3.2、创建Overlay 3.3、创建一个点 3.4、给点初始化点击事件 3.5、完整代码 四、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、代码实现 初始化变量&#xff1a; d…...

实战threeJS数字孪生开源 数字工厂

threeJS数字孪生 数字工厂 设备定位 基于three.js的数字工厂开源项目介绍 一、项目概述 本项目是一款基于three.js的数字工厂项目&#xff0c;旨在通过3D可视化技术&#xff0c;为工业制造领域提供一个直观、高效、智能的生产监控与管理平台。该项目结合了现代前端技术栈&…...

【Python基础篇】——第3篇:从入门到精通:掌握Python数据类型与数据结构

第3篇&#xff1a;数据类型与数据结构 目录 Python中的数据类型概述列表&#xff08;List&#xff09; 创建列表列表的基本操作列表方法列表推导式 元组&#xff08;Tuple&#xff09; 创建元组元组的基本操作元组的不可变性 字典&#xff08;Dictionary&#xff09; 创建字典…...

算法3(力扣83)-删除链表中的重复元素

1、题目&#xff1a;给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 2、实现&#xff08; 因为已排序&#xff0c;所以元素若重复&#xff0c;必然在其下一位&#xff09;&#xff08;这里为在vscod…...

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载,Scroll滚动到顶部

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载 效果展示 使用方法 import LoadingText from "../components/LoadingText" import PageToRefresh from "../components/PageToRefresh" import FooterBar from "../components/…...

.NET8.0多线程编码结合异步编码示例

1、创建一个.NET8.0控制台项目来演示多线程的应用 2、快速创建一个线程 3、多次运行程序&#xff0c;可以得到输出结果 这就是多线程的特点 - 当多个线程并行执行时&#xff0c;它们的具体执行顺序是不确定的&#xff0c;除非我们使用同步机制&#xff08;如 lock、信号量等&am…...

SpringBoot项目中解决CORS跨域资源共享问题

在Spring Boot项目中解决CORS&#xff08;跨域资源共享&#xff09;问题&#xff0c;可以通过以下几种方法&#xff1a; 1. 使用CrossOrigin注解 这是最简单的方法&#xff0c;适用于单个控制器或控制器方法级别的跨域配置。你可以在控制器类或具体的方法上使用CrossOrigin注…...

Android string.xml中特殊字符转义

项目中要在string.xml 中显示特殊符号 空格&#xff1a; &#xff08;普通的英文半角空格但不换行&#xff09; 窄空格&#xff1a;  &#xff08;中文全角空格 &#xff08;一个中文宽度&#xff09;&#xff09; &#xff08;半个中文宽度&#xff0c;但两个空格比一个中文…...

解析传统Workflow、AI Workflow与AI Agent概念,并通过Coze案例探讨利用AI工作流构建应用的实践流程

传统工作流 工作流入门这篇就够了 BPMN.JS中文教程 BPMN 工作流引擎解析 定义&#xff1a;工作流是在计算机支持下业务流程的自动或半自动化&#xff0c;其通过对流程进行描述以及按一定规则执行以完成相应工作。 应用&#xff1a;随着计算机技术的发展以及工业生产、办公自动…...

光谱相机的光谱分辨率可以达到多少?

多光谱相机 多光谱相机的光谱分辨率相对较低&#xff0c;波段数一般在 10 到 20 个左右&#xff0c;光谱分辨率通常在几十纳米到几百纳米之间&#xff0c;如常见的多光谱相机光谱分辨率为 100nm 左右。 高光谱相机 一般的高光谱相机光谱分辨率可达 2.5nm 到 10nm 左右&#x…...

android Recyclerview viewholder统一封装

Recyclerview holder 统一封装 ViewHolder类 import android.annotation.SuppressLint import android.content.Context import android.graphics.Color import android.graphics.drawable.GradientDrawable import android.os.Build import android.os.CountDownTimer import…...

Windows部署NVM并下载多版本Node.js的方法(含删除原有Node的方法)

本文介绍在Windows电脑中&#xff0c;下载、部署NVM&#xff08;node.js version management&#xff09;环境&#xff0c;并基于其安装不同版本的Node.js的方法。 在之前的文章Windows系统下载、部署Node.js与npm环境的方法&#xff08;https://blog.csdn.net/zhebushibiaoshi…...

51单片机入门基础

目录 一、基础知识储备 &#xff08;一&#xff09;了解51单片机的基本概念 &#xff08;二&#xff09;掌握数字电路基础 &#xff08;三&#xff09;学习C语言编程基础 二、开发环境搭建 &#xff08;一&#xff09;硬件准备 &#xff08;二&#xff09;软件准备 三、…...

老centos7 升级docker.io为docker-ce 脚本

旧的centos7 之前安装的是docker.io 由于一些原因,像docker compose 等版本变化,以及docker.io源受限等,我们要更新到docker-ce 并使用国内阿里云的源怎么处理?下面直接上脚本,upgrade-docker.sh #!/bin/bashset -e# 创建临时目录 TEMP_DIR"./tmp" mkdir -p "…...

数仓建模(三)建模三步走:需求分析、模型设计与数据加载

本文包含&#xff1a; 数据仓库的背景与重要性数据仓库建模的核心目标本文结构概览&#xff1a;需求分析、模型设计与数据加载 目录 第一部分&#xff1a;需求分析 1.1 需求分析的定义与目标 1.2 需求分析的步骤 1.2.1 业务需求收集 1.2.2 技术需求分析 1.2.3 成果输出…...

PHP xml 常用函数整理

————————-DOM 函数————————————– 1、DOMDocument->load() 作用&#xff1a;加载xml文件 用法&#xff1a;DOMDocument->load( string filename ) 参数&#xff1a;filename&#xff0c;xml文件&#xff1b; 返回&#xff1a;如果成功则返回 TRUE&a…...

数据结构(Java版)第八期:LinkedList与链表(三)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 目录 一、链表中的经典面试题 1.1. 链表分割 1.2. 链表的回文结构 1.3. 相交链表 1.4. 环形链表 一、链表中的经典面试题 1.1. 链表分割 题目中要求不能改变原来的数据顺序&#xff0c;也就是如上图所示。…...

数据结构学习记录-数据结构概念

1 数据结构&#xff1a; 数据结构是计算机存储&#xff0c;管理数据的方式。 数据必须依据某种逻辑联系组织在一起存储在计算机内 数据结构研究的就是这种数据的存储结构和数据的逻辑结构。 1.1 数据的逻辑结构&#xff1a; 逻辑结构指的是数据本身之间的关系 集合&#x…...

【Linux】11.Linux基础开发工具使用(4)

文章目录 3. Linux调试器-gdb使用3.1 背景3.2 下载安装3.3 使用gdb查询3.4 开始使用 3. Linux调试器-gdb使用 3.1 背景 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 要使用gdb调试&#xff0c;必须…...

数据结构与算法之栈: LeetCode 1047. 删除字符串中的所有相邻重复项 (Ts版)

删除字符串中的所有相邻重复项 https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/ 描述 给出由小写字母组成的字符串 s&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们在 s 上反复执行重复项删除操作&#xff0c;直到无…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…...