MapLibre GL JS第68课:点击符号时居中地图

GeoGPT+:用大模型理解地理语义的轻量级空间智能架构 地理空间智能正从专业GIS工具走向自然语言交互,其核心是将人类对位置、距离、范围、叠加等空间概念的理解,转化为可执行的空间查询与可视化。这背后依赖于大模型的空间语义解析能力与成熟GIS引擎的精准执行能力协同——即‘LLM做翻译官,GIS做施工队’的技术范式。GeoGPT+正是这一范式的工程化实践:它不生成坐标,而生成标准SQL+空间函数;不替代PostGIS或GeoPandas,而是桥接语义与计算。该架构已成功应用于森林火灾分析、城市内涝评估、林区风险建模等场景,显著降低空间分析门槛,让非技术人员通过‘说人 阅读详情

📌 学习目标

  • 掌握点击符号时居中地图的实现方法
  • 理解相关API的使用
  • 能够独立完成类似功能开发

MapLibre GL JS 从入门到精通 - 130+实战案例

🎯 核心概念

点击符号时将地图居中到该符号位置。

💻 完 整 代 码

代码示例

const map = new maplibregl.Map({
    container: 'map',
    style: 'https://demotiles.maplibre.org/style.json',
    center: [-90.96, -0.47],
    zoom: 7.5
});

map.on('load', async () => {
    // 添加图像作为自定义标记
    const image = await map.loadImage('https://maplibre.org/maplibre-gl-js/docs/assets/custom_marker.png');
    map.addImage('custom-marker', image.data);
    // 添加包含3个点的GeoJSON源。
    map.addSource('points', {
        'type': 'geojson',
        'data': {
            'type': 'FeatureCollection',
            'features': [
                {
                    'type': 'Feature',
                    'properties': {},
                    'geometry': {
                        'type': 'Point',
                        'coordinates': [
                            -91.395263671875,
                            -0.9145729757782163
                        ]
                    }
                },
                {
                    'type': 'Feature',
                    'properties': {},
                    'geometry': {
                        'type': 'Point',
                        'coordinates': [
                            -90.32958984375,
                            -0.6344474832838974
                        ]
                    }
                },
                {
                    'type': 'Feature',
                    'properties': {},
                    'geometry': {
                        'type': 'Point',
                        'coordinates': [
                            -91.34033203125,
                            0.01647949196029245
                        ]
                    }
                }
            ]
        }
    });

    // 添加符号图层
    map.addLayer({
        'id': 'symbols',
        'type': 'symbol',
        'source': 'points',
        'layout': {
            'icon-image': 'custom-marker'
        }
    });

    // 当点击'symbols'图层中的任何符号时,将地图居中到该符号的坐标。
    map.on('click', 'symbols', (e) => {
        map.flyTo({
            center: e.features[0].geometry.coordinates
        });
    });

    // 当鼠标进入'symbols'图层中的要素时,将光标更改为指针。
    map.on('mouseenter', 'symbols', () => {
        map.getCanvas().style.cursor = 'pointer';
    });

    // 当鼠标离开时,将其改回默认光标。
    map.on('mouseleave', 'symbols', () => {
        map.getCanvas().style.cursor = '';
    });
});

代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Center the map on a clicked symbol</title>
    <meta property="og:description" content="使用事件和 flyTo 将地图居中在符号上。" />
    <meta property="og:created" content="2006-06-25" />
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css' />
    <script src='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js'></script>
    <style>
        body { margin: 0; padding: 0; }
        html, body, #map { height: 100%; }
    </style>
</head>
<body>
<div id="map"></div>
<script>
    const map = new maplibregl.Map({
        container: 'map',
        style: 'https://demotiles.maplibre.org/style.json',
        center: [-90.96, -0.47],
        zoom: 7.5
    });

    map.on('load', async () => {
        // 添加图像作为自定义标记
        const image = await map.loadImage('https://maplibre.org/maplibre-gl-js/docs/assets/custom_marker.png');
        map.addImage('custom-marker', image.data);
        // 添加包含3个点的GeoJSON源。
        map.addSource('points', {
            'type': 'geojson',
            'data': {
                'type': 'FeatureCollection',
                'features': [
                    {
                        'type': 'Feature',
                        'properties': {},
                        'geometry': {
                            'type': 'Point',
                            'coordinates': [
                                -91.395263671875,
                                -0.9145729757782163
                            ]
                        }
                    },
                    {
                        'type': 'Feature',
                        'properties': {},
                        'geometry': {
                            'type': 'Point',
                            'coordinates': [
                                -90.32958984375,
                                -0.6344474832838974
                            ]
                        }
                    },
                    {
                        'type': 'Feature',
                        'properties': {},
                        'geometry': {
                            'type': 'Point',
                            'coordinates': [
                                -91.34033203125,
                                0.01647949196029245
                            ]
                        }
                    }
                ]
            }
        });

        // 添加符号图层
        map.addLayer({
            'id': 'symbols',
            'type': 'symbol',
            'source': 'points',
            'layout': {
                'icon-image': 'custom-marker'
            }
        });

        // 当点击'ssymbols'图层中的任何符号时,将地图居中到该符号的坐标。
        map.on('click', 'symbols', (e) => {
            map.flyTo({
                center: e.features[0].geometry.coordinates
            });
        });

        // 当鼠标进入'ssymbols'图层中的要素时,将光标更改为指针。
        map.on('mouseenter', 'symbols', () => {
            map.getCanvas().style.cursor = 'pointer';
        });

        // 当鼠标离开时,将其改回默认光标。
        map.on('mouseleave', 'symbols', () => {
            map.getCanvas().style.cursor = '';
        });
    });
</script>
</body>
</html>

🔍 代码解析

1. 初始化地图

使用 new maplibregl.Map() 创建地图实例,配置厄瓜多尔区域作为初始视图。

2. 关键配置项

  • map.loadImage(): 异步加载自定义标记图像
  • map.addImage(): 将图像添加到地图作为图标使用
  • map.flyTo(): 平滑飞到目标位置
  • mouseenter/mouseleave: 鼠标交互改变光标样式

⚙️ 参数说明

参数类型必填说明
center[number, number]是flyTo目标中心点
essentialboolean否动画是否必要,默认false

🎨 效果说明

在这里插入图片描述

运行代码后,地图显示厄瓜多尔区域,包含3个标记点。鼠标悬停在标记上时光标变为指针,点击任意标记,地图会以平滑飞行动画居中到该标记位置。

💡 常 见 问 题

Q1: 点击标记没有反应?
A: 检查以下几点:

  1. 确认图层已正确添加 map.addLayer()
  2. 确认事件监听器绑定在正确的图层ID上
  3. 检查浏览器控制台是否有错误

Q2: 飞行动画可以自定义吗?
A: 可以,flyTo支持speed、curve等参数控制动画效果:

map.flyTo({
    center: coordinates,
    speed: 2,
    curve: 1.5
});

Q3: 如何禁止飞行动画瞬间跳转?
A: 不调用flyTo而使用setCenter即可瞬间跳转:

map.setCenter(coordinates);

📝 练习任务

  1. 基础练习:修改GeoJSON数据中的坐标,添加更多标记点
  2. 进阶挑战:为飞行添加缩放和旋转效果
  3. 拓展思考:如何在飞行动画过程中显示进度?
  4. 综合实践:创建一个点击跳转的地图导览功能

🌟 最佳实践

  1. 动画平滑: 使用flyTo替代setCenter提供更好的用户体验
  2. 视觉反馈: 鼠标悬停时改变光标提示可点击
  3. 性能考虑: 避免频繁触发飞行动画
  4. 中止处理: 新飞行请求应中止当前动画
  5. 无障碍: 考虑提供键盘导航支持

🔗 延伸阅读


本文是MapLibre GL JS实践课程系列的一部分,欢迎关注收藏

如何处理动态语言(Python / JS)的“隐形”调用链? 本文揭示动态语言(Python/JS)中静态AST解析导致调用链“断链”的核心问题,提出通过运行时追踪补全图谱的解决方案。基于Code-Graph-RAG的cgr trace机制,分别利用pytest插件与V8 Profiler捕获真实调用路径,将动态边合并至静态图谱,并在权重体系中提升动态边优先级。实践表明,该方法可显著提升图谱覆盖率,实现“结构+行为”双视角理解代码,为MCP与Rerank系统提供可靠支持。 阅读详情

相关推荐

SpringBoot+Vue+MySQL 高校学科竞赛平台 完整可运行版(源码+文档)

本项目基于SpringBoot+Vue+MySQL构建高校学科竞赛管理平台,覆盖学生、教师、领队教师、管理员四大角色,实现竞赛发布、报名、刷题、评分、公示等全流程闭环管理。系统架构清晰,技术主流,配套完整源码、数据库脚本、万字论文、开题报告、答辩PPT及部署文档,支持一键运行,适用于毕业设计、课程设计及院系二次开发,真正实现“开箱即用”。

招风的黑耳优快云 171

MapLibre GL JS 从入门到精通 - 130+实战案例

本课程提供MapLibre GL JS的130+实战案例,系统讲解地图开发核心技术。内容涵盖基础地图显示、数据图层处理、样式可视化、交互动画、3D地形等高级功能,以及绘图工具、性能优化等应用。适合前端开发者、GIS工程师等学习,帮助掌握WebGL地图渲染原理,开发各类地图应用。课程包含大量可复用代码示例,从入门到进阶全面覆盖地图开发需求。

专注GIS软件开发。 660

SpringBoot+Vue 社区医院信息平台 完整源码+全套文档 开箱即用

本文介绍一套基于SpringBoot+Vue+MySQL的社区医院信息平台,覆盖患者、医生、护士、药品管理员、管理员五大角色,实现从挂号就诊、开方注射、取药结算到数据统计的全流程闭环管理。系统采用成熟技术栈,架构清晰,权限分明,配套完整源码、数据库脚本、万字论文、答辩PPT及部署文档,可直接用于毕业设计或基层医疗信息化落地,助力高效开发与快速交付。

招风的黑耳优快云 530

Web 版翻译者资料库

本项目是桌面版《翻译者资料库》的 Web 移植版,基于 Spring Boot 3.3、Thymeleaf、Bootstrap 5.3 与 MySQL 8.0 构建。它面向翻译写作提供资料、词汇、句库、文本工具、对照制作、查找、备份恢复及旧库迁移等功能,完整继承桌面版核心业务规则,支持一键启动与离线访问。

howard2005的专栏 147

【深度学习】tensorboard中的图片放到论文中

1. 利用tensorboard中的导出数据功能 选中左上角的标签,然后选择csv格式的数据下载即可。 左边的smoothing 数值不影响导出数据的大小。 2.tensorboard 图下标签介绍: 放大 Toggle y-axis log scale:将y轴对数化 Fit domain to data:如果拖动了图片等,再重新回到原始位置 Download Current Chart as SVG 3.用下载下来的csv数据来画图 第一幅图片:训练的平均长度 fig, ax1 = plt.sub

gaocui883的博客 1万+

3D视觉入门必看:深度图、点云图、IR图、RGB图像到底有什么区别?

本文深入解析了3D视觉中深度图、点云图、IR图与RGB图像的核心区别。深度图记录像素距离,是连接2D与3D的桥梁;点云图是显式的三维坐标集合;IR图感知红外光强度;RGB图像则提供颜色纹理。理解其信息维度和应用场景,是进行机器人导航、三维重建等任务的基础。

year5的博客 346

副队长BootStrap5探究(2)--按钮与按钮组

本文系统讲解Bootstrap 5按钮组件的使用与底层原理。通过CDN引入框架,掌握btn基础类及primary、success等主题色应用,学习轮廓按钮(btn-outline-*)、尺寸控制(btn-lg/sm)、块级布局(d-block)和禁用状态(disabled)等实用功能。结合源码解析,深入理解其基于CSS的圆角、过渡动画、伪类交互实现机制,实现“快速上手+原理掌握”的双重目标,助力前端技能进阶。

编程副队长 669

【MNE脑电信号处理学习笔记1】数据的读取、可视化、剪裁、滤波和保存

MNE之读取原始数据、可视化数据、剪裁数据、滤波和保存 Reading & visualizaing raw data, cropping, filtering, and saving 原视频教程:Pybrain: M/EEG analysis with MNE Python 原笔记和材料:pybrain_mne 本文根据视频和个人理解对原笔记进行细微修改。 Import the few packages we’ll need import matplotlib import pathlib i

小白家 4217

React 性能:memo / useMemo / useCallback

讲清 memo/useMemo/useCallback 的配合与边界,先测量再优化,避开常见过早优化。

JudithHuang的博客 328

手写中间件之——并行框架(1 并行框架的应用场景和需求)

我们为什么会需要一个带任务顺序编排的并行框架 1 复杂的微服务系统间调用 经常会有这样的调用场景:app(或web前端)调用后台的一个接口,该接口接到该请求后,需要调用其他多个微服务来获取数据,最终汇总一个最终结果返回给用户。 譬如用户请求“我的订单”,后台在收到请求后,就需要去调用用户详情rpc、商品详情rpc、库存rpc、优惠券rpc等等很多个服务。有些服务是可以并行去请求的,但有些服务...

tianyaleixiaowu的专栏 1万+

第14.7章 高翔博士最新开源框架Lightning-LM源码解读(七):PoseExtrapolator模块深度剖析,揭秘激光SLAM高频位姿外推核心技术

PoseExtrapolator是Lightning-LM框架中负责高频位姿外推的核心模块,通过融合DR(航位推算)、激光里程计和PGO(位姿图优化)数据实现精准实时定位。模块初始化依赖PGO数据,后续通过DR数据进行高频位姿更新,并利用PGO结果进行误差补偿。关键函数AddDRLocAndExtrapolate处理DR增量位姿,结合速度补偿机制逐步修正误差,保证高频输出的同时提升精度。该模块体现了多传感器融合思想,通过互补性数据(高频DR与低频高精PGO)实现鲁棒定位,代码中使用了SE3位姿表示、互斥锁保

行知SLAM 348

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 349

AUTOSAR模式管理-EcuM多核处理及其他概念

因此,EcuM不请求状态。因此,BswM必须确保,例如,在调用EcuM_GoHalt或EcuM_GoPoll之前,必须将关机目标从其默认值更改为ECUM_STATE_SLEEP。对于ECU的关闭,BswM(位于主EcuM的同一个分区中)最终调用主核上的GoOff,该GoOff将请求分发给所有的从核。在ECU Manager模块的早期版本中,睡眠目标被特殊处理,因为在ECU中实现的睡眠模式取决于ECU的功能。在使用了外部的SBC控制相关的MCU的下电的时候,在OFF阶段最后调用SBC进入到Sleep的指令。

m0_49148264的博客 1341

DSH (DeepSeek Harness) Windows 升级安装指南20261107

注意:如果在普通窗口执行 nvm 提示找不到命令,或执行 nvm use 提示 Access is denied,请务必关闭当前窗口,重新打开一个管理员CMD 执行上述完整路径命令。找到 .credentials.yaml,将其重命名为 .credentials.yaml.bak(备份并使其失效)。Node.js Storage Location:可改到非系统盘(如 D:\dev\nvm,避免路径含空格或中文)。打开文件资源管理器,进入 C:\Users<你的用户名>.dsh\。

fengye207161的博客 210

视觉Transformer实战 | Data-efficient image Transformer(DeiT)详解与实现

在计算机视觉领域,Vision Transformer (ViT) 已经证明了纯 Transformer 架构在图像分类任务上的强大能力。然而,ViT 通常需要在大规模数据集上预训练才能达到最佳性能,DeiT (Data-efficient image Transformer) 通过引入一系列训练策略和优化,使得 Transformer 模型能够在相对较小的数据集上取得优异表现。本节将详细介绍 DeiT 的技术原理,并使用 PyTorch 从零开始实现 DeiT 模型。

盼小辉丶的博客 1341

智能手环嵌入式系统:STM32+ESP8266多传感器健康监护设计

可穿戴健康监测设备是物联网与边缘计算融合的典型应用,其核心在于多源生理信号采集、低功耗实时处理及安全云协同。基于光电容积脉搏波(PPG)的心率与血氧检测、NTC热敏电阻体温测量、加速度-角速度融合跌倒判据等技术,构成了老年健康监护的基础感知能力;而STM32主控与ESP8266协处理器分工架构,则实现了计算资源与通信负载的高效解耦。该方案依托FreeRTOS多任务调度、阿里云IoT物模型标准化交互及MQTT双向通信,兼顾实时性、可靠性和工程可维护性,广泛适用于居家养老、慢病管理与远程健康预警等场景。

weixin_33256096的博客 99

SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在

# SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在 > 这是一套基于 Spring Boot 的服装销售平台源码,配套 `db.sql` 建表脚本,业务覆盖商品展示、购物车、订单流转、收货地址、订单评价、商品评论、在线客服、轮播图和资讯。形态是**前后台双端**:前台是顾客逛的商城,后台是管理员管的控制台。本文带你看清里面有什么、怎么跑

面朝大海 226

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

微信小程序-wxs

在微信开发者工具中右键创建.wxs后缀的文件。每个.wxs文件也是一个独立模块,同样使用导出内容。示例(文件return d;FOO: foo,bar: bar(外联定义参考官方文档)

dreams_dream的博客 349

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

汽车租赁系统(协同过滤算法、支付宝沙盒支付、 腾讯地图接入、WebSocket在线沟通、ECharts运营分析、三角色协同、还车费用处理)

本系统基于B/S架构,采用前后端分离设计,集成SpringBoot3、Vue2、MySQL等技术,实现用户、商家、管理员三角色协同管理。亮点包括:车型加权推荐与话题协同过滤算法提升个性化体验;支付宝沙盒支付、腾讯地图定位、WebSocket在线沟通保障流程闭环;还车费用智能计算与ECharts多维数据可视化助力运营分析,全面支持租车全生命周期管理。

paopaokaka_luck的博客 154

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

设计模式(unity游戏研发版)

当你使用图形用户界面类时通常会遇到一个问题。比如,你创建了自定义按钮类并允许客户端在按钮中注入自定义代码,这样当用户按下按钮时就会触发这些代码。观察者模式允许任何实现了订阅者接口的对象订阅发布者对象的事件通知。你可在按钮中添加订阅机制,允许客户端通过自定义订阅类注入自定义代码。在Unity中,这就像UnityEvent在Inspector中绑定多个回调。

m0_63330263的博客 104

使用echarts模拟甘特图

项目中需按时间段展示不同颜色的数据,通过解析时长并统计各类型总时长,结合预设颜色映射表(含自定义与默认色),动态生成ECharts图表。利用sumByTypeName聚合数据,为每类分配对应颜色,实现图例与柱状图的精准匹配,确保多时段、多类型数据可视化清晰准确。

uuai 29

【技术专题】JavaScript 网页技术 - JavaScript 流程控制

小锋老师推出《一天学会JavaScript(无废话版)》视频教程,涵盖基础语法、流程控制、函数、数组对象、DOM操作及ES6新特性。内容精炼,配套课件与源码打包下载,助力快速入门。重点讲解if/else、switch、for/while循环、for...of/in遍历及break/continue使用场景,并通过成绩判断实例演示实际应用。适合零基础学习者高效掌握核心技能。

java1234的博客 164

基于 FastAPI+LangChain+LangGraph+Agent+Vue3+MySQL 的房产数据采集与房价预测分析平台

本文介绍一个完整的「房产数据采集+AI房价预测」全栈项目,涵盖FastAPI异步后端、LangGraph Agent智能问答、爬虫采集、机器学习预测与Vue3前端,实现从数据采集到AI交互的闭环。项目融合多技术栈,具备真实业务场景与生产级设计(如降级策略、流式输出、多模型对比),兼具简历亮点与答辩演示优势,可系统性提升工程能力,并附高频面试题解析,是理想的技术综合实践项目。

深耕开发,专注编程实战。分享源码解析、项目搭建、问题排查笔记,沉淀技术,持续更新。 239

Vue3 低代码移动表单设计器实战(二):缩放画布下的拖拽系统与树状级联数据结构

本文深入剖析Vue3低代码表单设计器在缩放画布下的拖拽失效问题,揭示SortableJS在CSS Transform下坐标崩溃的数学根源。通过自研独立视觉克隆壳层与逆向几何补偿算法,实现精准拖拽;采用扁平数据存储+运行时树状计算结构,解决级联依赖与深克隆难题,确保逻辑一致性与性能优化,为复杂低代码系统提供可复用的工程范式。

NanChen的博客 347

LangGraph == 循环结构的实现

这是静态约束,不会参与运行时校验。主要作用是提升代码可读性、通过静态类型检查,同时帮助 LangGraph。也就是说,是否继续重试,在当前实现中主要由大模型决定,而不是由程序逻辑强制保证。因此,如果模型在多次工具调用失败后选择停止重试并生成最终回答,运行图不会阻止它。函数,也不再需要调用 add_conditional_edges()只要大模型持续返回工具调用,流程就会不断回到 llm_node。的缩写,即“推理 + 行动”架构。,运行时只负责判断具体走哪一条路径。

每天都要努力学习哦~~ 359

2026 年前端框架排行榜

前端框架是用于构建用户界面的工具集合,通过预设组件、网格系统和样式规范提升开发效率与可访问性。2026年主流框架包括:React(生态领先,适合全栈)、Next.js(SSR/SEO优化,主流选择)、Vue(学习友好,中小团队首选)、Angular(企业级稳定)、Svelte与Astro(性能突出)。趋势显示,服务端渲染、TypeScript、AI工具融合及轻量化成为关键方向。就业建议:优先学React+Next.js;追求易用选Vue;企业级项目可学Angular;追求极致性能可尝试Svelte或Astr

lxttzlove的博客 171
上一篇: MapLibre GL JS第67课:悬停显示弹窗
下一篇: MapLibre GL JS第69课:获取鼠标下的要素
丷丩
丷丩 优质创作者: 数据科学与机器学习技术领域 优质创作者: 数据科学与机器学习技术领域
博客等级 码龄18年 1万+粉丝 317原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丷丩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值